diff --git a/go.mod b/go.mod index c896810d3..dfc1326ab 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/cert-manager/cert-manager v1.16.2 github.com/charmbracelet/keygen v0.5.1 github.com/containers/image/v5 v5.33.0 - github.com/coreos/butane v0.22.0 + github.com/coreos/butane v0.23.0 github.com/diskfs/go-diskfs v1.4.2 github.com/go-logr/logr v1.4.2 github.com/go-playground/validator/v10 v10.22.1 @@ -113,7 +113,7 @@ require ( github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/coreos/ignition/v2 v2.18.0 // indirect + github.com/coreos/ignition/v2 v2.20.0 // indirect github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect diff --git a/go.sum b/go.sum index 95ce83cc3..bca33562c 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sir github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= github.com/containers/storage v1.56.0 h1:DZ9KSkj6M2tvj/4bBoaJu3QDHRl35BwsZ4kmLJS97ZI= github.com/containers/storage v1.56.0/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk= -github.com/coreos/butane v0.22.0 h1:nmXfiGqJMvPzBd2DfGyoayvO/KjpO6bES4uOEmtGTu8= -github.com/coreos/butane v0.22.0/go.mod h1:3OKS5qaH58O2yLAKgAtOgBpUQSm7aIOU09IpG+IvmF4= +github.com/coreos/butane v0.23.0 h1:C/005CtsUGilgoPDrODUkPbCbZ8OJDuS3c1ANUSZXro= +github.com/coreos/butane v0.23.0/go.mod h1:Oeoy3s0qNcJxyMa8kUYpxpJfnNPpAgxEbihwPtQNE1g= github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb h1:rmqyI19j3Z/74bIRhuC59RB442rXUazKNueVpfJPxg4= github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb/go.mod h1:rcFZM3uxVvdyNmsAV2jopgPD1cs5SPWJWU5dOz2LUnw= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -204,8 +204,8 @@ github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03V github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/ignition/v2 v2.18.0 h1:sPSGGsxaCuFMpKOMBQ71I9RIR20SIF4dWnoTomcPEYQ= -github.com/coreos/ignition/v2 v2.18.0/go.mod h1:TURPHDqWUWTmej8c+CEMBENMU3N/Lt6GfreHJuoDMbA= +github.com/coreos/ignition/v2 v2.20.0 h1:xQjrxhCbcSKpqrN2hOQavAc1rx0GOf6qh2QCauScwPU= +github.com/coreos/ignition/v2 v2.20.0/go.mod h1:l7EpXNWA7jBXmjUMvnVBlrrj+LX2wA/PAyD9kstwFDQ= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 h1:uSmlDgJGbUB0bwQBcZomBTottKwEDF5fF8UjSwKSzWM= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687/go.mod h1:Salmysdw7DAVuobBW/LwsKKgpyCPHUhjyJoMJD+ZJiI= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= diff --git a/vendor/github.com/coreos/butane/base/v0_6_exp/schema.go b/vendor/github.com/coreos/butane/base/v0_6/schema.go similarity index 98% rename from vendor/github.com/coreos/butane/base/v0_6_exp/schema.go rename to vendor/github.com/coreos/butane/base/v0_6/schema.go index 67e7b95c4..bb56c3722 100644 --- a/vendor/github.com/coreos/butane/base/v0_6_exp/schema.go +++ b/vendor/github.com/coreos/butane/base/v0_6/schema.go @@ -12,7 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v0_6_exp +package v0_6 + +type Cex struct { + Enabled *bool `yaml:"enabled"` +} type Clevis struct { Custom ClevisCustom `yaml:"custom"` @@ -119,6 +123,7 @@ type Link struct { } type Luks struct { + Cex Cex `yaml:"cex"` Clevis Clevis `yaml:"clevis"` Device *string `yaml:"device"` Discard *bool `yaml:"discard"` diff --git a/vendor/github.com/coreos/butane/base/v0_6_exp/translate.go b/vendor/github.com/coreos/butane/base/v0_6/translate.go similarity index 99% rename from vendor/github.com/coreos/butane/base/v0_6_exp/translate.go rename to vendor/github.com/coreos/butane/base/v0_6/translate.go index 8cf2395ff..769216845 100644 --- a/vendor/github.com/coreos/butane/base/v0_6_exp/translate.go +++ b/vendor/github.com/coreos/butane/base/v0_6/translate.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v0_6_exp +package v0_6 import ( "fmt" @@ -29,7 +29,7 @@ import ( "github.com/coreos/go-systemd/v22/unit" "github.com/coreos/ignition/v2/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_5/types" "github.com/coreos/vcontext/path" "github.com/coreos/vcontext/report" ) diff --git a/vendor/github.com/coreos/butane/base/v0_6_exp/util.go b/vendor/github.com/coreos/butane/base/v0_6/util.go similarity index 97% rename from vendor/github.com/coreos/butane/base/v0_6_exp/util.go rename to vendor/github.com/coreos/butane/base/v0_6/util.go index bdabebd54..fc0ce33e5 100644 --- a/vendor/github.com/coreos/butane/base/v0_6_exp/util.go +++ b/vendor/github.com/coreos/butane/base/v0_6/util.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v0_6_exp +package v0_6 import ( - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_5/types" ) type nodeTracker struct { diff --git a/vendor/github.com/coreos/butane/base/v0_6_exp/validate.go b/vendor/github.com/coreos/butane/base/v0_6/validate.go similarity index 99% rename from vendor/github.com/coreos/butane/base/v0_6_exp/validate.go rename to vendor/github.com/coreos/butane/base/v0_6/validate.go index ad3917be2..9c0d796aa 100644 --- a/vendor/github.com/coreos/butane/base/v0_6_exp/validate.go +++ b/vendor/github.com/coreos/butane/base/v0_6/validate.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v0_6_exp +package v0_6 import ( baseutil "github.com/coreos/butane/base/util" diff --git a/vendor/github.com/coreos/butane/base/v0_7_exp/schema.go b/vendor/github.com/coreos/butane/base/v0_7_exp/schema.go new file mode 100644 index 000000000..ecdeff1e4 --- /dev/null +++ b/vendor/github.com/coreos/butane/base/v0_7_exp/schema.go @@ -0,0 +1,267 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v0_7_exp + +type Cex struct { + Enabled *bool `yaml:"enabled"` +} + +type Clevis struct { + Custom ClevisCustom `yaml:"custom"` + Tang []Tang `yaml:"tang"` + Threshold *int `yaml:"threshold"` + Tpm2 *bool `yaml:"tpm2"` +} + +type ClevisCustom struct { + Config *string `yaml:"config"` + NeedsNetwork *bool `yaml:"needs_network"` + Pin *string `yaml:"pin"` +} + +type Config struct { + Version string `yaml:"version"` + Variant string `yaml:"variant"` + Ignition Ignition `yaml:"ignition"` + KernelArguments KernelArguments `yaml:"kernel_arguments"` + Passwd Passwd `yaml:"passwd"` + Storage Storage `yaml:"storage"` + Systemd Systemd `yaml:"systemd"` +} + +type Device string + +type Directory struct { + Group NodeGroup `yaml:"group"` + Overwrite *bool `yaml:"overwrite"` + Path string `yaml:"path"` + User NodeUser `yaml:"user"` + Mode *int `yaml:"mode"` +} + +type Disk struct { + Device string `yaml:"device"` + Partitions []Partition `yaml:"partitions"` + WipeTable *bool `yaml:"wipe_table"` +} + +type Dropin struct { + Contents *string `yaml:"contents"` + ContentsLocal *string `yaml:"contents_local"` + Name string `yaml:"name"` +} + +type File struct { + Group NodeGroup `yaml:"group"` + Overwrite *bool `yaml:"overwrite"` + Path string `yaml:"path"` + User NodeUser `yaml:"user"` + Append []Resource `yaml:"append"` + Contents Resource `yaml:"contents"` + Mode *int `yaml:"mode"` +} + +type Filesystem struct { + Device string `yaml:"device"` + Format *string `yaml:"format"` + Label *string `yaml:"label"` + MountOptions []string `yaml:"mount_options"` + Options []string `yaml:"options"` + Path *string `yaml:"path"` + UUID *string `yaml:"uuid"` + WipeFilesystem *bool `yaml:"wipe_filesystem"` + WithMountUnit *bool `yaml:"with_mount_unit" butane:"auto_skip"` // Added, not in Ignition spec +} + +type Group string + +type HTTPHeader struct { + Name string `yaml:"name"` + Value *string `yaml:"value"` +} + +type HTTPHeaders []HTTPHeader + +type Ignition struct { + Config IgnitionConfig `yaml:"config"` + Proxy Proxy `yaml:"proxy"` + Security Security `yaml:"security"` + Timeouts Timeouts `yaml:"timeouts"` +} + +type IgnitionConfig struct { + Merge []Resource `yaml:"merge"` + Replace Resource `yaml:"replace"` +} + +type KernelArgument string + +type KernelArguments struct { + ShouldExist []KernelArgument `yaml:"should_exist"` + ShouldNotExist []KernelArgument `yaml:"should_not_exist"` +} + +type Link struct { + Group NodeGroup `yaml:"group"` + Overwrite *bool `yaml:"overwrite"` + Path string `yaml:"path"` + User NodeUser `yaml:"user"` + Hard *bool `yaml:"hard"` + Target *string `yaml:"target"` +} + +type Luks struct { + Cex Cex `yaml:"cex"` + Clevis Clevis `yaml:"clevis"` + Device *string `yaml:"device"` + Discard *bool `yaml:"discard"` + KeyFile Resource `yaml:"key_file"` + Label *string `yaml:"label"` + Name string `yaml:"name"` + OpenOptions []string `yaml:"open_options"` + Options []string `yaml:"options"` + UUID *string `yaml:"uuid"` + WipeVolume *bool `yaml:"wipe_volume"` +} + +type NodeGroup struct { + ID *int `yaml:"id"` + Name *string `yaml:"name"` +} + +type NodeUser struct { + ID *int `yaml:"id"` + Name *string `yaml:"name"` +} + +type Partition struct { + GUID *string `yaml:"guid"` + Label *string `yaml:"label"` + Number int `yaml:"number"` + Resize *bool `yaml:"resize"` + ShouldExist *bool `yaml:"should_exist"` + SizeMiB *int `yaml:"size_mib"` + StartMiB *int `yaml:"start_mib"` + TypeGUID *string `yaml:"type_guid"` + WipePartitionEntry *bool `yaml:"wipe_partition_entry"` +} + +type Passwd struct { + Groups []PasswdGroup `yaml:"groups"` + Users []PasswdUser `yaml:"users"` +} + +type PasswdGroup struct { + Gid *int `yaml:"gid"` + Name string `yaml:"name"` + PasswordHash *string `yaml:"password_hash"` + ShouldExist *bool `yaml:"should_exist"` + System *bool `yaml:"system"` +} + +type PasswdUser struct { + Gecos *string `yaml:"gecos"` + Groups []Group `yaml:"groups"` + HomeDir *string `yaml:"home_dir"` + Name string `yaml:"name"` + NoCreateHome *bool `yaml:"no_create_home"` + NoLogInit *bool `yaml:"no_log_init"` + NoUserGroup *bool `yaml:"no_user_group"` + PasswordHash *string `yaml:"password_hash"` + PrimaryGroup *string `yaml:"primary_group"` + ShouldExist *bool `yaml:"should_exist"` + SSHAuthorizedKeys []SSHAuthorizedKey `yaml:"ssh_authorized_keys"` + SSHAuthorizedKeysLocal []string `yaml:"ssh_authorized_keys_local"` + Shell *string `yaml:"shell"` + System *bool `yaml:"system"` + UID *int `yaml:"uid"` +} + +type Proxy struct { + HTTPProxy *string `yaml:"http_proxy"` + HTTPSProxy *string `yaml:"https_proxy"` + NoProxy []string `yaml:"no_proxy"` +} + +type Raid struct { + Devices []Device `yaml:"devices"` + Level *string `yaml:"level"` + Name string `yaml:"name"` + Options []string `yaml:"options"` + Spares *int `yaml:"spares"` +} + +type Resource struct { + Compression *string `yaml:"compression"` + HTTPHeaders HTTPHeaders `yaml:"http_headers"` + Source *string `yaml:"source"` + Inline *string `yaml:"inline"` // Added, not in ignition spec + Local *string `yaml:"local"` // Added, not in ignition spec + Verification Verification `yaml:"verification"` +} + +type SSHAuthorizedKey string + +type Security struct { + TLS TLS `yaml:"tls"` +} + +type Storage struct { + Directories []Directory `yaml:"directories"` + Disks []Disk `yaml:"disks"` + Files []File `yaml:"files"` + Filesystems []Filesystem `yaml:"filesystems"` + Links []Link `yaml:"links"` + Luks []Luks `yaml:"luks"` + Raid []Raid `yaml:"raid"` + Trees []Tree `yaml:"trees" butane:"auto_skip"` // Added, not in ignition spec +} + +type Systemd struct { + Units []Unit `yaml:"units"` +} + +type Tang struct { + Thumbprint *string `yaml:"thumbprint"` + URL string `yaml:"url"` + Advertisement *string `yaml:"advertisement"` +} + +type TLS struct { + CertificateAuthorities []Resource `yaml:"certificate_authorities"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `yaml:"http_response_headers"` + HTTPTotal *int `yaml:"http_total"` +} + +type Tree struct { + Local string `yaml:"local"` + Path *string `yaml:"path"` +} + +type Unit struct { + Contents *string `yaml:"contents"` + ContentsLocal *string `yaml:"contents_local"` + Dropins []Dropin `yaml:"dropins"` + Enabled *bool `yaml:"enabled"` + Mask *bool `yaml:"mask"` + Name string `yaml:"name"` +} + +type Verification struct { + Hash *string `yaml:"hash"` +} diff --git a/vendor/github.com/coreos/butane/base/v0_7_exp/translate.go b/vendor/github.com/coreos/butane/base/v0_7_exp/translate.go new file mode 100644 index 000000000..6d4f65f21 --- /dev/null +++ b/vendor/github.com/coreos/butane/base/v0_7_exp/translate.go @@ -0,0 +1,501 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v0_7_exp + +import ( + "fmt" + "os" + slashpath "path" + "path/filepath" + "regexp" + "strings" + "text/template" + + baseutil "github.com/coreos/butane/base/util" + "github.com/coreos/butane/config/common" + "github.com/coreos/butane/translate" + + "github.com/coreos/go-systemd/v22/unit" + "github.com/coreos/ignition/v2/config/util" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +var ( + mountUnitTemplate = template.Must(template.New("unit").Parse(` +{{- define "options" }} + {{- if or .MountOptions .Remote }} +Options= + {{- range $i, $opt := .MountOptions }} + {{- if $i }},{{ end }} + {{- $opt }} + {{- end }} + {{- if .Remote }}{{ if .MountOptions }},{{ end }}_netdev{{ end }} + {{- end }} +{{- end -}} + +# Generated by Butane +{{- if .Swap }} +[Swap] +What={{.Device}} +{{- template "options" . }} + +[Install] +RequiredBy=swap.target +{{- else }} +[Unit] +Requires=systemd-fsck@{{.EscapedDevice}}.service +After=systemd-fsck@{{.EscapedDevice}}.service + +[Mount] +Where={{.Path}} +What={{.Device}} +Type={{.Format}} +{{- template "options" . }} + +[Install] +{{- if .Remote }} +RequiredBy=remote-fs.target +{{- else }} +RequiredBy=local-fs.target +{{- end }} +{{- end }}`)) +) + +// ToIgn3_6Unvalidated translates the config to an Ignition config. It also returns the set of translations +// it did so paths in the resultant config can be tracked back to their source in the source config. +// No config validation is performed on input or output. +func (c Config) ToIgn3_6Unvalidated(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { + ret := types.Config{} + + tr := translate.NewTranslator("yaml", "json", options) + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateFile) + tr.AddCustomTranslator(translateDirectory) + tr.AddCustomTranslator(translateLink) + tr.AddCustomTranslator(translateResource) + tr.AddCustomTranslator(translatePasswdUser) + tr.AddCustomTranslator(translateUnit) + + tm, r := translate.Prefixed(tr, "ignition", &c.Ignition, &ret.Ignition) + tm.AddTranslation(path.New("yaml", "version"), path.New("json", "ignition", "version")) + tm.AddTranslation(path.New("yaml", "ignition"), path.New("json", "ignition")) + translate.MergeP2(tr, tm, &r, "kernel_arguments", &c.KernelArguments, "kernelArguments", &ret.KernelArguments) + translate.MergeP(tr, tm, &r, "passwd", &c.Passwd, &ret.Passwd) + translate.MergeP(tr, tm, &r, "storage", &c.Storage, &ret.Storage) + translate.MergeP(tr, tm, &r, "systemd", &c.Systemd, &ret.Systemd) + + c.addMountUnits(&ret, &tm) + + tm2, r2 := c.processTrees(&ret, options) + tm.Merge(tm2) + r.Merge(r2) + + if r.IsFatal() { + return types.Config{}, translate.TranslationSet{}, r + } + return ret, tm, r +} + +func translateIgnition(from Ignition, options common.TranslateOptions) (to types.Ignition, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tr.AddCustomTranslator(translateResource) + to.Version = types.MaxVersion.String() + tm, r = translate.Prefixed(tr, "config", &from.Config, &to.Config) + translate.MergeP(tr, tm, &r, "proxy", &from.Proxy, &to.Proxy) + translate.MergeP(tr, tm, &r, "security", &from.Security, &to.Security) + translate.MergeP(tr, tm, &r, "timeouts", &from.Timeouts, &to.Timeouts) + return +} + +func translateFile(from File, options common.TranslateOptions) (to types.File, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tr.AddCustomTranslator(translateResource) + tm, r = translate.Prefixed(tr, "group", &from.Group, &to.Group) + translate.MergeP(tr, tm, &r, "user", &from.User, &to.User) + translate.MergeP(tr, tm, &r, "append", &from.Append, &to.Append) + translate.MergeP(tr, tm, &r, "contents", &from.Contents, &to.Contents) + translate.MergeP(tr, tm, &r, "overwrite", &from.Overwrite, &to.Overwrite) + translate.MergeP(tr, tm, &r, "path", &from.Path, &to.Path) + translate.MergeP(tr, tm, &r, "mode", &from.Mode, &to.Mode) + return +} + +func translateResource(from Resource, options common.TranslateOptions) (to types.Resource, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "verification", &from.Verification, &to.Verification) + translate.MergeP2(tr, tm, &r, "http_headers", &from.HTTPHeaders, "httpHeaders", &to.HTTPHeaders) + translate.MergeP(tr, tm, &r, "source", &from.Source, &to.Source) + translate.MergeP(tr, tm, &r, "compression", &from.Compression, &to.Compression) + + if from.Local != nil { + c := path.New("yaml", "local") + contents, err := baseutil.ReadLocalFile(*from.Local, options.FilesDir) + if err != nil { + r.AddOnError(c, err) + return + } + src, compression, err := baseutil.MakeDataURL(contents, to.Compression, !options.NoResourceAutoCompression) + if err != nil { + r.AddOnError(c, err) + return + } + to.Source = &src + tm.AddTranslation(c, path.New("json", "source")) + if compression != nil { + to.Compression = compression + tm.AddTranslation(c, path.New("json", "compression")) + } + } + + if from.Inline != nil { + c := path.New("yaml", "inline") + + src, compression, err := baseutil.MakeDataURL([]byte(*from.Inline), to.Compression, !options.NoResourceAutoCompression) + if err != nil { + r.AddOnError(c, err) + return + } + to.Source = &src + tm.AddTranslation(c, path.New("json", "source")) + if compression != nil { + to.Compression = compression + tm.AddTranslation(c, path.New("json", "compression")) + } + } + return +} + +func translateDirectory(from Directory, options common.TranslateOptions) (to types.Directory, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "group", &from.Group, &to.Group) + translate.MergeP(tr, tm, &r, "user", &from.User, &to.User) + translate.MergeP(tr, tm, &r, "overwrite", &from.Overwrite, &to.Overwrite) + translate.MergeP(tr, tm, &r, "path", &from.Path, &to.Path) + translate.MergeP(tr, tm, &r, "mode", &from.Mode, &to.Mode) + return +} + +func translateLink(from Link, options common.TranslateOptions) (to types.Link, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "group", &from.Group, &to.Group) + translate.MergeP(tr, tm, &r, "user", &from.User, &to.User) + translate.MergeP(tr, tm, &r, "target", &from.Target, &to.Target) + translate.MergeP(tr, tm, &r, "hard", &from.Hard, &to.Hard) + translate.MergeP(tr, tm, &r, "overwrite", &from.Overwrite, &to.Overwrite) + translate.MergeP(tr, tm, &r, "path", &from.Path, &to.Path) + return +} + +func translatePasswdUser(from PasswdUser, options common.TranslateOptions) (to types.PasswdUser, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "gecos", &from.Gecos, &to.Gecos) + translate.MergeP(tr, tm, &r, "groups", &from.Groups, &to.Groups) + translate.MergeP2(tr, tm, &r, "home_dir", &from.HomeDir, "homeDir", &to.HomeDir) + translate.MergeP(tr, tm, &r, "name", &from.Name, &to.Name) + translate.MergeP2(tr, tm, &r, "no_create_home", &from.NoCreateHome, "noCreateHome", &to.NoCreateHome) + translate.MergeP2(tr, tm, &r, "no_log_init", &from.NoLogInit, "noLogInit", &to.NoLogInit) + translate.MergeP2(tr, tm, &r, "no_user_group", &from.NoUserGroup, "noUserGroup", &to.NoUserGroup) + translate.MergeP2(tr, tm, &r, "password_hash", &from.PasswordHash, "passwordHash", &to.PasswordHash) + translate.MergeP2(tr, tm, &r, "primary_group", &from.PrimaryGroup, "primaryGroup", &to.PrimaryGroup) + translate.MergeP(tr, tm, &r, "shell", &from.Shell, &to.Shell) + translate.MergeP2(tr, tm, &r, "should_exist", &from.ShouldExist, "shouldExist", &to.ShouldExist) + translate.MergeP2(tr, tm, &r, "ssh_authorized_keys", &from.SSHAuthorizedKeys, "sshAuthorizedKeys", &to.SSHAuthorizedKeys) + translate.MergeP(tr, tm, &r, "system", &from.System, &to.System) + translate.MergeP(tr, tm, &r, "uid", &from.UID, &to.UID) + + if len(from.SSHAuthorizedKeysLocal) > 0 { + c := path.New("yaml", "ssh_authorized_keys_local") + tm.AddTranslation(c, path.New("json", "sshAuthorizedKeys")) + + if options.FilesDir == "" { + r.AddOnError(c, common.ErrNoFilesDir) + return + } + + for keyFileIndex, sshKeyFile := range from.SSHAuthorizedKeysLocal { + sshKeys, err := baseutil.ReadLocalFile(sshKeyFile, options.FilesDir) + if err != nil { + r.AddOnError(c.Append(keyFileIndex), err) + continue + } + for _, line := range regexp.MustCompile("\r?\n").Split(string(sshKeys), -1) { + if line == "" { + continue + } + tm.AddTranslation(c.Append(keyFileIndex), path.New("json", "sshAuthorizedKeys", len(to.SSHAuthorizedKeys))) + to.SSHAuthorizedKeys = append(to.SSHAuthorizedKeys, types.SSHAuthorizedKey(line)) + } + } + } + + return +} + +func translateUnit(from Unit, options common.TranslateOptions) (to types.Unit, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tr.AddCustomTranslator(translateDropin) + tm, r = translate.Prefixed(tr, "contents", &from.Contents, &to.Contents) + translate.MergeP(tr, tm, &r, "dropins", &from.Dropins, &to.Dropins) + translate.MergeP(tr, tm, &r, "enabled", &from.Enabled, &to.Enabled) + translate.MergeP(tr, tm, &r, "mask", &from.Mask, &to.Mask) + translate.MergeP(tr, tm, &r, "name", &from.Name, &to.Name) + + if util.NotEmpty(from.ContentsLocal) { + c := path.New("yaml", "contents_local") + contents, err := baseutil.ReadLocalFile(*from.ContentsLocal, options.FilesDir) + if err != nil { + r.AddOnError(c, err) + return + } + tm.AddTranslation(c, path.New("json", "contents")) + to.Contents = util.StrToPtr(string(contents)) + } + + return +} + +func translateDropin(from Dropin, options common.TranslateOptions) (to types.Dropin, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "contents", &from.Contents, &to.Contents) + translate.MergeP(tr, tm, &r, "name", &from.Name, &to.Name) + + if util.NotEmpty(from.ContentsLocal) { + c := path.New("yaml", "contents_local") + contents, err := baseutil.ReadLocalFile(*from.ContentsLocal, options.FilesDir) + if err != nil { + r.AddOnError(c, err) + return + } + tm.AddTranslation(c, path.New("json", "contents")) + to.Contents = util.StrToPtr(string(contents)) + } + + return +} + +func (c Config) processTrees(ret *types.Config, options common.TranslateOptions) (translate.TranslationSet, report.Report) { + ts := translate.NewTranslationSet("yaml", "json") + var r report.Report + if len(c.Storage.Trees) == 0 { + return ts, r + } + t := newNodeTracker(ret) + + for i, tree := range c.Storage.Trees { + yamlPath := path.New("yaml", "storage", "trees", i) + if options.FilesDir == "" { + r.AddOnError(yamlPath, common.ErrNoFilesDir) + return ts, r + } + + // calculate base path within FilesDir and check for + // path traversal + srcBaseDir := filepath.Join(options.FilesDir, filepath.FromSlash(tree.Local)) + if err := baseutil.EnsurePathWithinFilesDir(srcBaseDir, options.FilesDir); err != nil { + r.AddOnError(yamlPath, err) + continue + } + info, err := os.Stat(srcBaseDir) + if err != nil { + r.AddOnError(yamlPath, err) + continue + } + if !info.IsDir() { + r.AddOnError(yamlPath, common.ErrTreeNotDirectory) + continue + } + destBaseDir := "/" + if util.NotEmpty(tree.Path) { + destBaseDir = *tree.Path + } + + walkTree(yamlPath, &ts, &r, t, srcBaseDir, destBaseDir, options) + } + return ts, r +} + +func walkTree(yamlPath path.ContextPath, ts *translate.TranslationSet, r *report.Report, t *nodeTracker, srcBaseDir, destBaseDir string, options common.TranslateOptions) { + // The strategy for errors within WalkFunc is to add an error to + // the report and return nil, so walking continues but translation + // will fail afterward. + err := filepath.Walk(srcBaseDir, func(srcPath string, info os.FileInfo, err error) error { + if err != nil { + r.AddOnError(yamlPath, err) + return nil + } + relPath, err := filepath.Rel(srcBaseDir, srcPath) + if err != nil { + r.AddOnError(yamlPath, err) + return nil + } + destPath := slashpath.Join(destBaseDir, filepath.ToSlash(relPath)) + + if info.Mode().IsDir() { + return nil + } else if info.Mode().IsRegular() { + i, file := t.GetFile(destPath) + if file != nil { + if util.NotEmpty(file.Contents.Source) { + r.AddOnError(yamlPath, common.ErrNodeExists) + return nil + } + } else { + if t.Exists(destPath) { + r.AddOnError(yamlPath, common.ErrNodeExists) + return nil + } + i, file = t.AddFile(types.File{ + Node: types.Node{ + Path: destPath, + }, + }) + ts.AddFromCommonSource(yamlPath, path.New("json", "storage", "files", i), file) + if i == 0 { + ts.AddTranslation(yamlPath, path.New("json", "storage", "files")) + } + } + contents, err := os.ReadFile(srcPath) + if err != nil { + r.AddOnError(yamlPath, err) + return nil + } + url, compression, err := baseutil.MakeDataURL(contents, file.Contents.Compression, !options.NoResourceAutoCompression) + if err != nil { + r.AddOnError(yamlPath, err) + return nil + } + file.Contents.Source = &url + ts.AddTranslation(yamlPath, path.New("json", "storage", "files", i, "contents", "source")) + if compression != nil { + file.Contents.Compression = compression + ts.AddTranslation(yamlPath, path.New("json", "storage", "files", i, "contents", "compression")) + } + ts.AddTranslation(yamlPath, path.New("json", "storage", "files", i, "contents")) + if file.Mode == nil { + mode := 0644 + if info.Mode()&0111 != 0 { + mode = 0755 + } + file.Mode = &mode + ts.AddTranslation(yamlPath, path.New("json", "storage", "files", i, "mode")) + } + } else if info.Mode()&os.ModeType == os.ModeSymlink { + i, link := t.GetLink(destPath) + if link != nil { + if util.NotEmpty(link.Target) { + r.AddOnError(yamlPath, common.ErrNodeExists) + return nil + } + } else { + if t.Exists(destPath) { + r.AddOnError(yamlPath, common.ErrNodeExists) + return nil + } + i, link = t.AddLink(types.Link{ + Node: types.Node{ + Path: destPath, + }, + }) + ts.AddFromCommonSource(yamlPath, path.New("json", "storage", "links", i), link) + if i == 0 { + ts.AddTranslation(yamlPath, path.New("json", "storage", "links")) + } + } + target, err := os.Readlink(srcPath) + if err != nil { + r.AddOnError(yamlPath, err) + return nil + } + link.Target = util.StrToPtr(filepath.ToSlash(target)) + ts.AddTranslation(yamlPath, path.New("json", "storage", "links", i, "target")) + } else { + r.AddOnError(yamlPath, common.ErrFileType) + return nil + } + return nil + }) + r.AddOnError(yamlPath, err) +} + +func (c Config) addMountUnits(config *types.Config, ts *translate.TranslationSet) { + if len(c.Storage.Filesystems) == 0 { + return + } + var rendered types.Config + renderedTranslations := translate.NewTranslationSet("yaml", "json") + renderedTranslations.AddTranslation(path.New("yaml", "storage", "filesystems"), path.New("json", "systemd")) + renderedTranslations.AddTranslation(path.New("yaml", "storage", "filesystems"), path.New("json", "systemd", "units")) + for i, fs := range c.Storage.Filesystems { + if !util.IsTrue(fs.WithMountUnit) { + continue + } + fromPath := path.New("yaml", "storage", "filesystems", i, "with_mount_unit") + remote := false + // check filesystems targeting /dev/mapper devices against LUKS to determine if a + // remote mount is needed + if strings.HasPrefix(fs.Device, "/dev/mapper/") || strings.HasPrefix(fs.Device, "/dev/disk/by-id/dm-name-") { + for _, luks := range c.Storage.Luks { + // LUKS devices are opened with their name specified + if fs.Device == fmt.Sprintf("/dev/mapper/%s", luks.Name) || fs.Device == fmt.Sprintf("/dev/disk/by-id/dm-name-%s", luks.Name) { + if len(luks.Clevis.Tang) > 0 { + remote = true + break + } + } + } + } + newUnit := mountUnitFromFS(fs, remote) + unitPath := path.New("json", "systemd", "units", len(rendered.Systemd.Units)) + rendered.Systemd.Units = append(rendered.Systemd.Units, newUnit) + renderedTranslations.AddFromCommonSource(fromPath, unitPath, newUnit) + } + retConfig, retTranslations := baseutil.MergeTranslatedConfigs(rendered, renderedTranslations, *config, *ts) + *config = retConfig.(types.Config) + *ts = retTranslations +} + +func mountUnitFromFS(fs Filesystem, remote bool) types.Unit { + context := struct { + *Filesystem + EscapedDevice string + Remote bool + Swap bool + }{ + Filesystem: &fs, + EscapedDevice: unit.UnitNamePathEscape(fs.Device), + Remote: remote, + // unchecked deref of format ok, fs would fail validation otherwise + Swap: *fs.Format == "swap", + } + contents := strings.Builder{} + err := mountUnitTemplate.Execute(&contents, context) + if err != nil { + panic(err) + } + var unitName string + if context.Swap { + unitName = unit.UnitNamePathEscape(fs.Device) + ".swap" + } else { + // unchecked deref of path ok, fs would fail validation otherwise + unitName = unit.UnitNamePathEscape(*fs.Path) + ".mount" + } + return types.Unit{ + Name: unitName, + Enabled: util.BoolToPtr(true), + Contents: util.StrToPtr(contents.String()), + } +} diff --git a/vendor/github.com/coreos/butane/base/v0_7_exp/util.go b/vendor/github.com/coreos/butane/base/v0_7_exp/util.go new file mode 100644 index 000000000..dbbd7d292 --- /dev/null +++ b/vendor/github.com/coreos/butane/base/v0_7_exp/util.go @@ -0,0 +1,125 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v0_7_exp + +import ( + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" +) + +type nodeTracker struct { + files *[]types.File + fileMap map[string]int + + dirs *[]types.Directory + dirMap map[string]int + + links *[]types.Link + linkMap map[string]int +} + +func newNodeTracker(c *types.Config) *nodeTracker { + t := nodeTracker{ + files: &c.Storage.Files, + fileMap: make(map[string]int, len(c.Storage.Files)), + + dirs: &c.Storage.Directories, + dirMap: make(map[string]int, len(c.Storage.Directories)), + + links: &c.Storage.Links, + linkMap: make(map[string]int, len(c.Storage.Links)), + } + for i, n := range *t.files { + t.fileMap[n.Path] = i + } + for i, n := range *t.dirs { + t.dirMap[n.Path] = i + } + for i, n := range *t.links { + t.linkMap[n.Path] = i + } + return &t +} + +func (t *nodeTracker) Exists(path string) bool { + for _, m := range []map[string]int{t.fileMap, t.dirMap, t.linkMap} { + if _, ok := m[path]; ok { + return true + } + } + return false +} + +func (t *nodeTracker) GetFile(path string) (int, *types.File) { + if i, ok := t.fileMap[path]; ok { + return i, &(*t.files)[i] + } else { + return 0, nil + } +} + +func (t *nodeTracker) AddFile(f types.File) (int, *types.File) { + if f.Path == "" { + panic("File path missing") + } + if _, ok := t.fileMap[f.Path]; ok { + panic("Adding already existing file") + } + i := len(*t.files) + *t.files = append(*t.files, f) + t.fileMap[f.Path] = i + return i, &(*t.files)[i] +} + +func (t *nodeTracker) GetDir(path string) (int, *types.Directory) { + if i, ok := t.dirMap[path]; ok { + return i, &(*t.dirs)[i] + } else { + return 0, nil + } +} + +func (t *nodeTracker) AddDir(d types.Directory) (int, *types.Directory) { + if d.Path == "" { + panic("Directory path missing") + } + if _, ok := t.dirMap[d.Path]; ok { + panic("Adding already existing directory") + } + i := len(*t.dirs) + *t.dirs = append(*t.dirs, d) + t.dirMap[d.Path] = i + return i, &(*t.dirs)[i] +} + +func (t *nodeTracker) GetLink(path string) (int, *types.Link) { + if i, ok := t.linkMap[path]; ok { + return i, &(*t.links)[i] + } else { + return 0, nil + } +} + +func (t *nodeTracker) AddLink(l types.Link) (int, *types.Link) { + if l.Path == "" { + panic("Link path missing") + } + if _, ok := t.linkMap[l.Path]; ok { + panic("Adding already existing link") + } + i := len(*t.links) + *t.links = append(*t.links, l) + t.linkMap[l.Path] = i + return i, &(*t.links)[i] +} diff --git a/vendor/github.com/coreos/butane/base/v0_7_exp/validate.go b/vendor/github.com/coreos/butane/base/v0_7_exp/validate.go new file mode 100644 index 000000000..2d7c69e6c --- /dev/null +++ b/vendor/github.com/coreos/butane/base/v0_7_exp/validate.go @@ -0,0 +1,92 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v0_7_exp + +import ( + baseutil "github.com/coreos/butane/base/util" + "github.com/coreos/butane/config/common" + + "github.com/coreos/ignition/v2/config/util" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (rs Resource) Validate(c path.ContextPath) (r report.Report) { + var field string + sources := 0 + if rs.Local != nil { + sources++ + field = "local" + } + if rs.Inline != nil { + sources++ + field = "inline" + } + if rs.Source != nil { + sources++ + field = "source" + } + if sources > 1 { + r.AddOnError(c.Append(field), common.ErrTooManyResourceSources) + } + return +} + +func (fs Filesystem) Validate(c path.ContextPath) (r report.Report) { + if !util.IsTrue(fs.WithMountUnit) { + return + } + if util.NilOrEmpty(fs.Format) { + r.AddOnError(c.Append("format"), common.ErrMountUnitNoFormat) + } else if *fs.Format != "swap" && util.NilOrEmpty(fs.Path) { + r.AddOnError(c.Append("path"), common.ErrMountUnitNoPath) + } + return +} + +func (d Directory) Validate(c path.ContextPath) (r report.Report) { + if d.Mode != nil { + r.AddOnWarn(c.Append("mode"), baseutil.CheckForDecimalMode(*d.Mode, true)) + } + return +} + +func (f File) Validate(c path.ContextPath) (r report.Report) { + if f.Mode != nil { + r.AddOnWarn(c.Append("mode"), baseutil.CheckForDecimalMode(*f.Mode, false)) + } + return +} + +func (t Tree) Validate(c path.ContextPath) (r report.Report) { + if t.Local == "" { + r.AddOnError(c, common.ErrTreeNoLocal) + } + return +} + +func (rs Unit) Validate(c path.ContextPath) (r report.Report) { + if rs.ContentsLocal != nil && rs.Contents != nil { + r.AddOnError(c.Append("contents_local"), common.ErrTooManySystemdSources) + } + return +} + +func (rs Dropin) Validate(c path.ContextPath) (r report.Report) { + if rs.ContentsLocal != nil && rs.Contents != nil { + r.AddOnError(c.Append("contents_local"), common.ErrTooManySystemdSources) + } + return +} diff --git a/vendor/github.com/coreos/butane/config/common/errors.go b/vendor/github.com/coreos/butane/config/common/errors.go index 922111ab7..71f3c0d22 100644 --- a/vendor/github.com/coreos/butane/config/common/errors.go +++ b/vendor/github.com/coreos/butane/config/common/errors.go @@ -59,6 +59,8 @@ var ( ErrNoLuksBootDevice = errors.New("device is required for layouts: s390x-eckd, s390x-zfcp") ErrMirrorNotSupport = errors.New("mirroring not supported on layouts: s390x-eckd, s390x-zfcp, s390x-virt") ErrLuksBootDeviceBadName = errors.New("device name must start with /dev/dasd on s390x-eckd layout or /dev/sd on s390x-zfcp layout") + ErrCexArchitectureMismatch = errors.New("when using cex the targeted architecture must match s390x") + ErrCexNotSupported = errors.New("cex is not currently supported on the target platform") // partition ErrReuseByLabel = errors.New("partitions cannot be reused by label; number must be specified except on boot disk (/dev/disk/by-id/coreos-boot-disk) or when wipe_table is true") diff --git a/vendor/github.com/coreos/butane/config/config.go b/vendor/github.com/coreos/butane/config/config.go index 831e9c75c..93aa2a032 100644 --- a/vendor/github.com/coreos/butane/config/config.go +++ b/vendor/github.com/coreos/butane/config/config.go @@ -24,7 +24,8 @@ import ( fcos1_3 "github.com/coreos/butane/config/fcos/v1_3" fcos1_4 "github.com/coreos/butane/config/fcos/v1_4" fcos1_5 "github.com/coreos/butane/config/fcos/v1_5" - fcos1_6_exp "github.com/coreos/butane/config/fcos/v1_6_exp" + fcos1_6 "github.com/coreos/butane/config/fcos/v1_6" + fcos1_7_exp "github.com/coreos/butane/config/fcos/v1_7_exp" fiot1_0 "github.com/coreos/butane/config/fiot/v1_0" fiot1_1_exp "github.com/coreos/butane/config/fiot/v1_1_exp" flatcar1_0 "github.com/coreos/butane/config/flatcar/v1_0" @@ -37,8 +38,9 @@ import ( openshift4_14 "github.com/coreos/butane/config/openshift/v4_14" openshift4_15 "github.com/coreos/butane/config/openshift/v4_15" openshift4_16 "github.com/coreos/butane/config/openshift/v4_16" - openshift4_17_exp "github.com/coreos/butane/config/openshift/v4_17" - openshift4_18_exp "github.com/coreos/butane/config/openshift/v4_18_exp" + openshift4_17 "github.com/coreos/butane/config/openshift/v4_17" + openshift4_18 "github.com/coreos/butane/config/openshift/v4_18" + openshift4_19_exp "github.com/coreos/butane/config/openshift/v4_19_exp" openshift4_8 "github.com/coreos/butane/config/openshift/v4_8" openshift4_9 "github.com/coreos/butane/config/openshift/v4_9" r4e1_0 "github.com/coreos/butane/config/r4e/v1_0" @@ -67,10 +69,11 @@ func init() { RegisterTranslator("fcos", "1.3.0", fcos1_3.ToIgn3_2Bytes) RegisterTranslator("fcos", "1.4.0", fcos1_4.ToIgn3_3Bytes) RegisterTranslator("fcos", "1.5.0", fcos1_5.ToIgn3_4Bytes) - RegisterTranslator("fcos", "1.6.0-experimental", fcos1_6_exp.ToIgn3_5Bytes) + RegisterTranslator("fcos", "1.6.0", fcos1_6.ToIgn3_5Bytes) + RegisterTranslator("fcos", "1.7.0-experimental", fcos1_7_exp.ToIgn3_6Bytes) RegisterTranslator("flatcar", "1.0.0", flatcar1_0.ToIgn3_3Bytes) RegisterTranslator("flatcar", "1.1.0", flatcar1_1.ToIgn3_4Bytes) - RegisterTranslator("flatcar", "1.2.0-experimental", flatcar1_2_exp.ToIgn3_5Bytes) + RegisterTranslator("flatcar", "1.2.0-experimental", flatcar1_2_exp.ToIgn3_6Bytes) RegisterTranslator("openshift", "4.8.0", openshift4_8.ToConfigBytes) RegisterTranslator("openshift", "4.9.0", openshift4_9.ToConfigBytes) RegisterTranslator("openshift", "4.10.0", openshift4_10.ToConfigBytes) @@ -80,13 +83,14 @@ func init() { RegisterTranslator("openshift", "4.14.0", openshift4_14.ToConfigBytes) RegisterTranslator("openshift", "4.15.0", openshift4_15.ToConfigBytes) RegisterTranslator("openshift", "4.16.0", openshift4_16.ToConfigBytes) - RegisterTranslator("openshift", "4.17.0", openshift4_17_exp.ToConfigBytes) - RegisterTranslator("openshift", "4.18.0-experimental", openshift4_18_exp.ToConfigBytes) + RegisterTranslator("openshift", "4.17.0", openshift4_17.ToConfigBytes) + RegisterTranslator("openshift", "4.18.0", openshift4_18.ToConfigBytes) + RegisterTranslator("openshift", "4.19.0-experimental", openshift4_19_exp.ToConfigBytes) RegisterTranslator("r4e", "1.0.0", r4e1_0.ToIgn3_3Bytes) RegisterTranslator("r4e", "1.1.0", r4e1_1.ToIgn3_4Bytes) - RegisterTranslator("r4e", "1.2.0-experimental", r4e1_2_exp.ToIgn3_5Bytes) + RegisterTranslator("r4e", "1.2.0-experimental", r4e1_2_exp.ToIgn3_6Bytes) RegisterTranslator("fiot", "1.0.0", fiot1_0.ToIgn3_4Bytes) - RegisterTranslator("fiot", "1.1.0-experimental", fiot1_1_exp.ToIgn3_5Bytes) + RegisterTranslator("fiot", "1.1.0-experimental", fiot1_1_exp.ToIgn3_6Bytes) RegisterTranslator("rhcos", "0.1.0", unsupportedRhcosVariant) } diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/schema.go b/vendor/github.com/coreos/butane/config/fcos/v1_6/schema.go similarity index 93% rename from vendor/github.com/coreos/butane/config/fcos/v1_6_exp/schema.go rename to vendor/github.com/coreos/butane/config/fcos/v1_6/schema.go index 52cdfb43e..dd63a0836 100644 --- a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/schema.go +++ b/vendor/github.com/coreos/butane/config/fcos/v1_6/schema.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v1_6_exp +package v1_6 import ( - base "github.com/coreos/butane/base/v0_6_exp" + base "github.com/coreos/butane/base/v0_6" ) type Config struct { @@ -31,6 +31,7 @@ type BootDevice struct { } type BootDeviceLuks struct { + Cex base.Cex `yaml:"cex"` Discard *bool `yaml:"discard"` Device *string `yaml:"device"` Tang []base.Tang `yaml:"tang"` diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/translate.go b/vendor/github.com/coreos/butane/config/fcos/v1_6/translate.go similarity index 83% rename from vendor/github.com/coreos/butane/config/fcos/v1_6_exp/translate.go rename to vendor/github.com/coreos/butane/config/fcos/v1_6/translate.go index a7c0a679e..2d24cc912 100644 --- a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/translate.go +++ b/vendor/github.com/coreos/butane/config/fcos/v1_6/translate.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v1_6_exp +package v1_6 import ( "fmt" @@ -24,7 +24,7 @@ import ( "github.com/coreos/butane/translate" "github.com/coreos/ignition/v2/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_5/types" "github.com/coreos/vcontext/path" "github.com/coreos/vcontext/report" ) @@ -114,7 +114,7 @@ func (c Config) processBootDevice(config *types.Config, ts *translate.Translatio var r report.Report // check for high-level features - wantLuks := util.IsTrue(c.BootDevice.Luks.Tpm2) || len(c.BootDevice.Luks.Tang) > 0 + wantLuks := util.IsTrue(c.BootDevice.Luks.Tpm2) || len(c.BootDevice.Luks.Tang) > 0 || util.IsTrue(c.BootDevice.Luks.Cex.Enabled) wantMirror := len(c.BootDevice.Mirror.Devices) > 0 if !wantLuks && !wantMirror { return r @@ -252,25 +252,47 @@ func (c Config) processBootDevice(config *types.Config, ts *translate.Translatio default: luksDevice = "/dev/disk/by-partlabel/root" } - clevis, ts2, r2 := translateBootDeviceLuks(c.BootDevice.Luks, options) - rendered.Storage.Luks = []types.Luks{{ - Clevis: clevis, - Device: &luksDevice, - Discard: c.BootDevice.Luks.Discard, - Label: util.StrToPtr("luks-root"), - Name: "root", - WipeVolume: util.BoolToPtr(true), - }} - lpath := path.New("yaml", "boot_device", "luks") - rpath := path.New("json", "storage", "luks", 0) - renderedTranslations.Merge(ts2.PrefixPaths(lpath, rpath.Append("clevis"))) - renderedTranslations.AddTranslation(lpath.Append("discard"), rpath.Append("discard")) - for _, f := range []string{"device", "label", "name", "wipeVolume"} { - renderedTranslations.AddTranslation(lpath, rpath.Append(f)) + if util.IsTrue(c.BootDevice.Luks.Cex.Enabled) { + cex, ts2, r2 := translateBootDeviceLuksCex(c.BootDevice.Luks, options) + rendered.Storage.Luks = []types.Luks{{ + Cex: cex, + Device: &luksDevice, + Discard: c.BootDevice.Luks.Discard, + Label: util.StrToPtr("luks-root"), + Name: "root", + WipeVolume: util.BoolToPtr(true), + }} + lpath := path.New("yaml", "boot_device", "luks") + rpath := path.New("json", "storage", "luks", 0) + renderedTranslations.Merge(ts2.PrefixPaths(lpath, rpath.Append("cex"))) + renderedTranslations.AddTranslation(lpath.Append("discard"), rpath.Append("discard")) + for _, f := range []string{"device", "label", "name", "wipeVolume"} { + renderedTranslations.AddTranslation(lpath, rpath.Append(f)) + } + renderedTranslations.AddTranslation(lpath, rpath) + renderedTranslations.AddTranslation(lpath, path.New("json", "storage", "luks")) + r.Merge(r2) + } else { + clevis, ts2, r2 := translateBootDeviceLuks(c.BootDevice.Luks, options) + rendered.Storage.Luks = []types.Luks{{ + Clevis: clevis, + Device: &luksDevice, + Discard: c.BootDevice.Luks.Discard, + Label: util.StrToPtr("luks-root"), + Name: "root", + WipeVolume: util.BoolToPtr(true), + }} + lpath := path.New("yaml", "boot_device", "luks") + rpath := path.New("json", "storage", "luks", 0) + renderedTranslations.Merge(ts2.PrefixPaths(lpath, rpath.Append("clevis"))) + renderedTranslations.AddTranslation(lpath.Append("discard"), rpath.Append("discard")) + for _, f := range []string{"device", "label", "name", "wipeVolume"} { + renderedTranslations.AddTranslation(lpath, rpath.Append(f)) + } + renderedTranslations.AddTranslation(lpath, rpath) + renderedTranslations.AddTranslation(lpath, path.New("json", "storage", "luks")) + r.Merge(r2) } - renderedTranslations.AddTranslation(lpath, rpath) - renderedTranslations.AddTranslation(lpath, path.New("json", "storage", "luks")) - r.Merge(r2) } // create root filesystem @@ -317,6 +339,19 @@ func translateBootDeviceLuks(from BootDeviceLuks, options common.TranslateOption return } +func translateBootDeviceLuksCex(from BootDeviceLuks, options common.TranslateOptions) (to types.Cex, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + // Discard field is handled by the caller because it doesn't go + // into types.Cex + tm, r = translate.Prefixed(tr, "enabled", &from.Cex.Enabled, &to.Enabled) + translate.MergeP(tr, tm, &r, "enabled", &from.Cex.Enabled, &to.Enabled) + // we're being called manually, not via the translate package's + // custom translator mechanism, so we have to add the base + // translation ourselves + tm.AddTranslation(path.New("yaml"), path.New("json")) + return +} + func (c Config) handleUserGrubCfg(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { rendered := types.Config{} ts := translate.NewTranslationSet("yaml", "json") diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/validate.go b/vendor/github.com/coreos/butane/config/fcos/v1_6/validate.go similarity index 73% rename from vendor/github.com/coreos/butane/config/fcos/v1_6_exp/validate.go rename to vendor/github.com/coreos/butane/config/fcos/v1_6/validate.go index 481e3d847..35e5a4c13 100644 --- a/vendor/github.com/coreos/butane/config/fcos/v1_6_exp/validate.go +++ b/vendor/github.com/coreos/butane/config/fcos/v1_6/validate.go @@ -12,12 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v1_6_exp +package v1_6 import ( "regexp" + "strings" "github.com/coreos/butane/config/common" + "github.com/coreos/ignition/v2/config/shared/errors" "github.com/coreos/ignition/v2/config/util" "github.com/coreos/vcontext/path" @@ -54,29 +56,42 @@ func (d BootDevice) Validate(c path.ContextPath) (r report.Report) { if d.Layout != nil { switch *d.Layout { case "aarch64", "ppc64le", "x86_64": + // Nothing to do case "s390x-eckd": if util.NilOrEmpty(d.Luks.Device) { - r.AddOnError(c.Append(*d.Layout), common.ErrNoLuksBootDevice) + r.AddOnError(c.Append("layout"), common.ErrNoLuksBootDevice) } else if !dasdRe.MatchString(*d.Luks.Device) { - r.AddOnError(c.Append(*d.Layout), common.ErrLuksBootDeviceBadName) + r.AddOnError(c.Append("layout"), common.ErrLuksBootDeviceBadName) } case "s390x-zfcp": if util.NilOrEmpty(d.Luks.Device) { - r.AddOnError(c.Append(*d.Layout), common.ErrNoLuksBootDevice) + r.AddOnError(c.Append("layout"), common.ErrNoLuksBootDevice) } else if !sdRe.MatchString(*d.Luks.Device) { - r.AddOnError(c.Append(*d.Layout), common.ErrLuksBootDeviceBadName) + r.AddOnError(c.Append("layout"), common.ErrLuksBootDeviceBadName) } case "s390x-virt": default: r.AddOnError(c.Append("layout"), common.ErrUnknownBootDeviceLayout) } - if *d.Layout == "s390x-eckd" || *d.Layout == "s390x-zfcp" || *d.Layout == "s390x-virt" { - if len(d.Mirror.Devices) > 0 { - r.AddOnError(c.Append(*d.Layout), common.ErrMirrorNotSupport) - } + // Mirroring the boot disk is not supported on s390x + if strings.HasPrefix(*d.Layout, "s390x") && len(d.Mirror.Devices) > 0 { + r.AddOnError(c.Append("layout"), common.ErrMirrorNotSupport) + } + } + + // CEX is only valid on s390x and incompatible with Clevis + if util.IsTrue(d.Luks.Cex.Enabled) { + if d.Layout == nil { + r.AddOnError(c.Append("luks", "cex"), common.ErrCexArchitectureMismatch) + } else if !strings.HasPrefix(*d.Layout, "s390x") { + r.AddOnError(c.Append("layout"), common.ErrCexArchitectureMismatch) + } + if len(d.Luks.Tang) > 0 || util.IsTrue(d.Luks.Tpm2) { + r.AddOnError(c.Append("luks"), errors.ErrCexWithClevis) } } + r.Merge(d.Mirror.Validate(c.Append("mirror"))) return } diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/schema.go b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/schema.go new file mode 100644 index 000000000..b58c15b1f --- /dev/null +++ b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/schema.go @@ -0,0 +1,53 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v1_7_exp + +import ( + base "github.com/coreos/butane/base/v0_7_exp" +) + +type Config struct { + base.Config `yaml:",inline"` + BootDevice BootDevice `yaml:"boot_device"` + Grub Grub `yaml:"grub"` +} + +type BootDevice struct { + Layout *string `yaml:"layout"` + Luks BootDeviceLuks `yaml:"luks"` + Mirror BootDeviceMirror `yaml:"mirror"` +} + +type BootDeviceLuks struct { + Cex base.Cex `yaml:"cex"` + Discard *bool `yaml:"discard"` + Device *string `yaml:"device"` + Tang []base.Tang `yaml:"tang"` + Threshold *int `yaml:"threshold"` + Tpm2 *bool `yaml:"tpm2"` +} + +type BootDeviceMirror struct { + Devices []string `yaml:"devices"` +} + +type Grub struct { + Users []GrubUser `yaml:"users"` +} + +type GrubUser struct { + Name string `yaml:"name"` + PasswordHash *string `yaml:"password_hash"` +} diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/translate.go b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/translate.go new file mode 100644 index 000000000..bd31358eb --- /dev/null +++ b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/translate.go @@ -0,0 +1,413 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v1_7_exp + +import ( + "fmt" + "strings" + + baseutil "github.com/coreos/butane/base/util" + "github.com/coreos/butane/config/common" + cutil "github.com/coreos/butane/config/util" + "github.com/coreos/butane/translate" + + "github.com/coreos/ignition/v2/config/util" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +const ( + reservedTypeGuid = "8DA63339-0007-60C0-C436-083AC8230908" + biosTypeGuid = "21686148-6449-6E6F-744E-656564454649" + prepTypeGuid = "9E1A2D38-C612-4316-AA26-8B49521E5A8B" + espTypeGuid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" + + // The partition layout implemented in this file replicates + // the layout of the OS image defined in: + // https://github.com/coreos/coreos-assembler/blob/main/src/create_disk.sh + // + // It's not critical that we match that layout exactly; the hard + // constraints are: + // - The desugared partition cannot be smaller than the one it + // replicates + // - The new BIOS-BOOT partition (and maybe the PReP one?) must be + // at the same offset as the original + // + // Do not change these constants! New partition layouts must be + // encoded into new layout templates. + reservedV1SizeMiB = 1 + biosV1SizeMiB = 1 + prepV1SizeMiB = 4 + espV1SizeMiB = 127 + bootV1SizeMiB = 384 +) + +// Return FieldFilters for this spec. +func (c Config) FieldFilters() *cutil.FieldFilters { + return nil +} + +// ToIgn3_6Unvalidated translates the config to an Ignition config. It also +// returns the set of translations it did so paths in the resultant config +// can be tracked back to their source in the source config. No config +// validation is performed on input or output. +func (c Config) ToIgn3_6Unvalidated(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { + ret, ts, r := c.Config.ToIgn3_6Unvalidated(options) + if r.IsFatal() { + return types.Config{}, translate.TranslationSet{}, r + } + r.Merge(c.processBootDevice(&ret, &ts, options)) + for i, disk := range ret.Storage.Disks { + // In the boot_device.mirror case, nothing specifies partition numbers + // so match existing partitions only when `wipeTable` is false + if !util.IsTrue(disk.WipeTable) { + for j, partition := range disk.Partitions { + // check for reserved partlabels + if partition.Label != nil { + if (*partition.Label == "BIOS-BOOT" && partition.Number != 1) || (*partition.Label == "PowerPC-PReP-boot" && partition.Number != 1) || (*partition.Label == "EFI-SYSTEM" && partition.Number != 2) || (*partition.Label == "boot" && partition.Number != 3) || (*partition.Label == "root" && partition.Number != 4) { + r.AddOnWarn(path.New("json", "storage", "disks", i, "partitions", j, "label"), common.ErrWrongPartitionNumber) + } + } + } + } + } + + retp, tsp, rp := c.handleUserGrubCfg(options) + retConfig, ts := baseutil.MergeTranslatedConfigs(retp, tsp, ret, ts) + ret = retConfig.(types.Config) + r.Merge(rp) + return ret, ts, r +} + +// ToIgn3_6 translates the config to an Ignition config. It returns a +// report of any errors or warnings in the source and resultant config. If +// the report has fatal errors or it encounters other problems translating, +// an error is returned. +func (c Config) ToIgn3_6(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_6Unvalidated", options) + return cfg.(types.Config), r, err +} + +// ToIgn3_6Bytes translates from a v1.6 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or +// warnings in the source and resultant config. If the report has fatal errors or it encounters other problems +// translating, an error is returned. +func ToIgn3_6Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_6", options) +} + +func (c Config) processBootDevice(config *types.Config, ts *translate.TranslationSet, options common.TranslateOptions) report.Report { + var rendered types.Config + renderedTranslations := translate.NewTranslationSet("yaml", "json") + var r report.Report + + // check for high-level features + wantLuks := util.IsTrue(c.BootDevice.Luks.Tpm2) || len(c.BootDevice.Luks.Tang) > 0 || util.IsTrue(c.BootDevice.Luks.Cex.Enabled) + wantMirror := len(c.BootDevice.Mirror.Devices) > 0 + if !wantLuks && !wantMirror { + return r + } + + // compute layout rendering options + var wantBIOSPart bool + var wantEFIPart bool + var wantPRePPart bool + layout := c.BootDevice.Layout + switch { + case layout == nil || *layout == "x86_64": + wantBIOSPart = true + wantEFIPart = true + case *layout == "aarch64": + wantEFIPart = true + case *layout == "ppc64le": + wantPRePPart = true + case *layout == "s390x-eckd" || *layout == "s390x-virt" || *layout == "s390x-zfcp": + default: + // should have failed validation + panic("unknown layout") + } + + // mirrored root disk + if wantMirror { + // partition disks + for i, device := range c.BootDevice.Mirror.Devices { + labelIndex := len(rendered.Storage.Disks) + 1 + disk := types.Disk{ + Device: device, + WipeTable: util.BoolToPtr(true), + } + if wantBIOSPart { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("bios-%d", labelIndex)), + SizeMiB: util.IntToPtr(biosV1SizeMiB), + TypeGUID: util.StrToPtr(biosTypeGuid), + }) + } else if wantPRePPart { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("prep-%d", labelIndex)), + SizeMiB: util.IntToPtr(prepV1SizeMiB), + TypeGUID: util.StrToPtr(prepTypeGuid), + }) + } else { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("reserved-%d", labelIndex)), + SizeMiB: util.IntToPtr(reservedV1SizeMiB), + TypeGUID: util.StrToPtr(reservedTypeGuid), + }) + } + if wantEFIPart { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("esp-%d", labelIndex)), + SizeMiB: util.IntToPtr(espV1SizeMiB), + TypeGUID: util.StrToPtr(espTypeGuid), + }) + } else { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("reserved-%d", labelIndex)), + SizeMiB: util.IntToPtr(reservedV1SizeMiB), + TypeGUID: util.StrToPtr(reservedTypeGuid), + }) + } + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("boot-%d", labelIndex)), + SizeMiB: util.IntToPtr(bootV1SizeMiB), + }, types.Partition{ + Label: util.StrToPtr(fmt.Sprintf("root-%d", labelIndex)), + }) + renderedTranslations.AddFromCommonSource(path.New("yaml", "boot_device", "mirror", "devices", i), path.New("json", "storage", "disks", len(rendered.Storage.Disks)), disk) + rendered.Storage.Disks = append(rendered.Storage.Disks, disk) + + if wantEFIPart { + // add ESP filesystem + espFilesystem := types.Filesystem{ + Device: fmt.Sprintf("/dev/disk/by-partlabel/esp-%d", labelIndex), + Format: util.StrToPtr("vfat"), + Label: util.StrToPtr(fmt.Sprintf("esp-%d", labelIndex)), + WipeFilesystem: util.BoolToPtr(true), + } + renderedTranslations.AddFromCommonSource(path.New("yaml", "boot_device", "mirror", "devices", i), path.New("json", "storage", "filesystems", len(rendered.Storage.Filesystems)), espFilesystem) + rendered.Storage.Filesystems = append(rendered.Storage.Filesystems, espFilesystem) + } + } + renderedTranslations.AddTranslation(path.New("yaml", "boot_device", "mirror", "devices"), path.New("json", "storage", "disks")) + + // create RAIDs + raidDevices := func(labelPrefix string) []types.Device { + count := len(rendered.Storage.Disks) + ret := make([]types.Device, count) + for i := 0; i < count; i++ { + ret[i] = types.Device(fmt.Sprintf("/dev/disk/by-partlabel/%s-%d", labelPrefix, i+1)) + } + return ret + } + rendered.Storage.Raid = []types.Raid{{ + Devices: raidDevices("boot"), + Level: util.StrToPtr("raid1"), + Name: "md-boot", + // put the RAID superblock at the end of the + // partition so BIOS GRUB doesn't need to + // understand RAID + Options: []types.RaidOption{"--metadata=1.0"}, + }, { + Devices: raidDevices("root"), + Level: util.StrToPtr("raid1"), + Name: "md-root", + }} + renderedTranslations.AddFromCommonSource(path.New("yaml", "boot_device", "mirror"), path.New("json", "storage", "raid"), rendered.Storage.Raid) + + // create boot filesystem + bootFilesystem := types.Filesystem{ + Device: "/dev/md/md-boot", + Format: util.StrToPtr("ext4"), + Label: util.StrToPtr("boot"), + WipeFilesystem: util.BoolToPtr(true), + } + renderedTranslations.AddFromCommonSource(path.New("yaml", "boot_device", "mirror"), path.New("json", "storage", "filesystems", len(rendered.Storage.Filesystems)), bootFilesystem) + rendered.Storage.Filesystems = append(rendered.Storage.Filesystems, bootFilesystem) + } + + // encrypted root partition + if wantLuks { + var luksDevice string + switch { + //Luks Device for dasd and zFCP-scsi + case layout != nil && *layout == "s390x-eckd": + luksDevice = *c.BootDevice.Luks.Device + "2" + case layout != nil && *layout == "s390x-zfcp": + luksDevice = *c.BootDevice.Luks.Device + "4" + case wantMirror: + luksDevice = "/dev/md/md-root" + default: + luksDevice = "/dev/disk/by-partlabel/root" + } + if util.IsTrue(c.BootDevice.Luks.Cex.Enabled) { + cex, ts2, r2 := translateBootDeviceLuksCex(c.BootDevice.Luks, options) + rendered.Storage.Luks = []types.Luks{{ + Cex: cex, + Device: &luksDevice, + Discard: c.BootDevice.Luks.Discard, + Label: util.StrToPtr("luks-root"), + Name: "root", + WipeVolume: util.BoolToPtr(true), + }} + lpath := path.New("yaml", "boot_device", "luks") + rpath := path.New("json", "storage", "luks", 0) + renderedTranslations.Merge(ts2.PrefixPaths(lpath, rpath.Append("cex"))) + renderedTranslations.AddTranslation(lpath.Append("discard"), rpath.Append("discard")) + for _, f := range []string{"device", "label", "name", "wipeVolume"} { + renderedTranslations.AddTranslation(lpath, rpath.Append(f)) + } + renderedTranslations.AddTranslation(lpath, rpath) + renderedTranslations.AddTranslation(lpath, path.New("json", "storage", "luks")) + r.Merge(r2) + } else { + clevis, ts2, r2 := translateBootDeviceLuks(c.BootDevice.Luks, options) + rendered.Storage.Luks = []types.Luks{{ + Clevis: clevis, + Device: &luksDevice, + Discard: c.BootDevice.Luks.Discard, + Label: util.StrToPtr("luks-root"), + Name: "root", + WipeVolume: util.BoolToPtr(true), + }} + lpath := path.New("yaml", "boot_device", "luks") + rpath := path.New("json", "storage", "luks", 0) + renderedTranslations.Merge(ts2.PrefixPaths(lpath, rpath.Append("clevis"))) + renderedTranslations.AddTranslation(lpath.Append("discard"), rpath.Append("discard")) + for _, f := range []string{"device", "label", "name", "wipeVolume"} { + renderedTranslations.AddTranslation(lpath, rpath.Append(f)) + } + renderedTranslations.AddTranslation(lpath, rpath) + renderedTranslations.AddTranslation(lpath, path.New("json", "storage", "luks")) + r.Merge(r2) + } + } + + // create root filesystem + var rootDevice string + switch { + case wantLuks: + // LUKS, or LUKS on RAID + rootDevice = "/dev/mapper/root" + case wantMirror: + // RAID without LUKS + rootDevice = "/dev/md/md-root" + default: + panic("can't happen") + } + rootFilesystem := types.Filesystem{ + Device: rootDevice, + Format: util.StrToPtr("xfs"), + Label: util.StrToPtr("root"), + WipeFilesystem: util.BoolToPtr(true), + } + renderedTranslations.AddFromCommonSource(path.New("yaml", "boot_device"), path.New("json", "storage", "filesystems", len(rendered.Storage.Filesystems)), rootFilesystem) + renderedTranslations.AddTranslation(path.New("yaml", "boot_device"), path.New("json", "storage", "filesystems")) + rendered.Storage.Filesystems = append(rendered.Storage.Filesystems, rootFilesystem) + + // merge with translated config + renderedTranslations.AddTranslation(path.New("yaml", "boot_device"), path.New("json", "storage")) + retConfig, retTranslations := baseutil.MergeTranslatedConfigs(rendered, renderedTranslations, *config, *ts) + *config = retConfig.(types.Config) + *ts = retTranslations + return r +} + +func translateBootDeviceLuks(from BootDeviceLuks, options common.TranslateOptions) (to types.Clevis, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + // Discard field is handled by the caller because it doesn't go + // into types.Clevis + tm, r = translate.Prefixed(tr, "tang", &from.Tang, &to.Tang) + translate.MergeP(tr, tm, &r, "threshold", &from.Threshold, &to.Threshold) + translate.MergeP(tr, tm, &r, "tpm2", &from.Tpm2, &to.Tpm2) + // we're being called manually, not via the translate package's + // custom translator mechanism, so we have to add the base + // translation ourselves + tm.AddTranslation(path.New("yaml"), path.New("json")) + return +} + +func translateBootDeviceLuksCex(from BootDeviceLuks, options common.TranslateOptions) (to types.Cex, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + // Discard field is handled by the caller because it doesn't go + // into types.Cex + tm, r = translate.Prefixed(tr, "enabled", &from.Cex.Enabled, &to.Enabled) + translate.MergeP(tr, tm, &r, "enabled", &from.Cex.Enabled, &to.Enabled) + // we're being called manually, not via the translate package's + // custom translator mechanism, so we have to add the base + // translation ourselves + tm.AddTranslation(path.New("yaml"), path.New("json")) + return +} + +func (c Config) handleUserGrubCfg(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { + rendered := types.Config{} + ts := translate.NewTranslationSet("yaml", "json") + var r report.Report + yamlPath := path.New("yaml", "grub", "users") + if len(c.Grub.Users) == 0 { + // No users + return rendered, ts, r + } + + // create boot filesystem + rendered.Storage.Filesystems = append(rendered.Storage.Filesystems, + types.Filesystem{ + Device: "/dev/disk/by-label/boot", + Format: util.StrToPtr("ext4"), + Path: util.StrToPtr("/boot"), + }) + + userCfgContent := []byte(buildGrubConfig(c.Grub)) + src, compression, err := baseutil.MakeDataURL(userCfgContent, nil, !options.NoResourceAutoCompression) + if err != nil { + r.AddOnError(yamlPath, err) + return rendered, ts, r + } + + // Create user.cfg file and add it to rendered config + rendered.Storage.Files = append(rendered.Storage.Files, + types.File{ + Node: types.Node{ + Path: "/boot/grub2/user.cfg", + }, + FileEmbedded1: types.FileEmbedded1{ + Append: []types.Resource{ + { + Source: util.StrToPtr(src), + Compression: compression, + }, + }, + }, + }) + + ts.AddFromCommonSource(yamlPath, path.New("json", "storage"), rendered.Storage) + return rendered, ts, r +} + +func buildGrubConfig(gb Grub) string { + // Process super users and corresponding passwords + allUsers := []string{} + cmds := []string{} + + for _, user := range gb.Users { + // We have already validated that user.Name and user.PasswordHash are non-empty + allUsers = append(allUsers, user.Name) + // Command for setting users password + cmds = append(cmds, fmt.Sprintf("password_pbkdf2 %s %s", user.Name, *user.PasswordHash)) + } + superUserCmd := fmt.Sprintf("set superusers=\"%s\"\n", strings.Join(allUsers, " ")) + return "# Generated by Butane\n\n" + superUserCmd + strings.Join(cmds, "\n") + "\n" +} diff --git a/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/validate.go b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/validate.go new file mode 100644 index 000000000..e84ed1e64 --- /dev/null +++ b/vendor/github.com/coreos/butane/config/fcos/v1_7_exp/validate.go @@ -0,0 +1,115 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v1_7_exp + +import ( + "regexp" + "strings" + + "github.com/coreos/butane/config/common" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +const rootDevice = "/dev/disk/by-id/coreos-boot-disk" + +var allowedMountpoints = regexp.MustCompile(`^/(etc|var)(/|$)`) +var dasdRe = regexp.MustCompile("(/dev/dasd[a-z]$)") +var sdRe = regexp.MustCompile("(/dev/sd[a-z]$)") + +// We can't define a Validate function directly on Disk because that's defined in base, +// so we use a Validate function on the top-level Config instead. +func (conf Config) Validate(c path.ContextPath) (r report.Report) { + for i, disk := range conf.Storage.Disks { + if disk.Device != rootDevice && !util.IsTrue(disk.WipeTable) { + for p, partition := range disk.Partitions { + if partition.Number == 0 && partition.Label != nil { + r.AddOnWarn(c.Append("storage", "disks", i, "partitions", p, "number"), common.ErrReuseByLabel) + } + } + } + } + for i, fs := range conf.Storage.Filesystems { + if fs.Path != nil && !allowedMountpoints.MatchString(*fs.Path) && util.IsTrue(fs.WithMountUnit) { + r.AddOnError(c.Append("storage", "filesystems", i, "path"), common.ErrMountPointForbidden) + } + } + return +} + +func (d BootDevice) Validate(c path.ContextPath) (r report.Report) { + if d.Layout != nil { + switch *d.Layout { + case "aarch64", "ppc64le", "x86_64": + // Nothing to do + case "s390x-eckd": + if util.NilOrEmpty(d.Luks.Device) { + r.AddOnError(c.Append("layout"), common.ErrNoLuksBootDevice) + } else if !dasdRe.MatchString(*d.Luks.Device) { + r.AddOnError(c.Append("layout"), common.ErrLuksBootDeviceBadName) + } + case "s390x-zfcp": + if util.NilOrEmpty(d.Luks.Device) { + r.AddOnError(c.Append("layout"), common.ErrNoLuksBootDevice) + } else if !sdRe.MatchString(*d.Luks.Device) { + r.AddOnError(c.Append("layout"), common.ErrLuksBootDeviceBadName) + } + case "s390x-virt": + default: + r.AddOnError(c.Append("layout"), common.ErrUnknownBootDeviceLayout) + } + + // Mirroring the boot disk is not supported on s390x + if strings.HasPrefix(*d.Layout, "s390x") && len(d.Mirror.Devices) > 0 { + r.AddOnError(c.Append("layout"), common.ErrMirrorNotSupport) + } + } + + // CEX is only valid on s390x and incompatible with Clevis + if util.IsTrue(d.Luks.Cex.Enabled) { + if d.Layout == nil { + r.AddOnError(c.Append("luks", "cex"), common.ErrCexArchitectureMismatch) + } else if !strings.HasPrefix(*d.Layout, "s390x") { + r.AddOnError(c.Append("layout"), common.ErrCexArchitectureMismatch) + } + if len(d.Luks.Tang) > 0 || util.IsTrue(d.Luks.Tpm2) { + r.AddOnError(c.Append("luks"), errors.ErrCexWithClevis) + } + } + + r.Merge(d.Mirror.Validate(c.Append("mirror"))) + return +} + +func (m BootDeviceMirror) Validate(c path.ContextPath) (r report.Report) { + if len(m.Devices) == 1 { + r.AddOnError(c.Append("devices"), common.ErrTooFewMirrorDevices) + } + return +} + +func (user GrubUser) Validate(c path.ContextPath) (r report.Report) { + if user.Name == "" { + r.AddOnError(c.Append("name"), common.ErrGrubUserNameNotSpecified) + } + + if !util.NotEmpty(user.PasswordHash) { + r.AddOnError(c.Append("password_hash"), common.ErrGrubPasswordNotSpecified) + } + return +} diff --git a/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/schema.go b/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/schema.go index e8e5c4159..20868d01f 100644 --- a/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/schema.go +++ b/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/schema.go @@ -15,7 +15,7 @@ package v1_1_exp import ( - base "github.com/coreos/butane/base/v0_6_exp" + base "github.com/coreos/butane/base/v0_7_exp" ) type Config struct { diff --git a/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/translate.go b/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/translate.go index 9ecac218f..abba699ca 100644 --- a/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/translate.go +++ b/vendor/github.com/coreos/butane/config/fiot/v1_1_exp/translate.go @@ -18,7 +18,7 @@ import ( "github.com/coreos/butane/config/common" cutil "github.com/coreos/butane/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" "github.com/coreos/vcontext/report" ) @@ -37,18 +37,18 @@ func (c Config) FieldFilters() *cutil.FieldFilters { return &fieldFilters } -// ToIgn3_5 translates the config to an Ignition config. It returns a +// ToIgn3_6 translates the config to an Ignition config. It returns a // report of any errors or warnings in the source and resultant config. If // the report has fatal errors or it encounters other problems translating, // an error is returned. -func (c Config) ToIgn3_5(options common.TranslateOptions) (types.Config, report.Report, error) { - cfg, r, err := cutil.Translate(c, "ToIgn3_5Unvalidated", options) +func (c Config) ToIgn3_6(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_6Unvalidated", options) return cfg.(types.Config), r, err } -// ToIgn3_5Bytes translates from a v1.2 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or +// ToIgn3_6Bytes translates from a v1.2 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or // warnings in the source and resultant config. If the report has fatal errors or it encounters other problems // translating, an error is returned. -func ToIgn3_5Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { - return cutil.TranslateBytes(input, &Config{}, "ToIgn3_5", options) +func ToIgn3_6Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_6", options) } diff --git a/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/schema.go b/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/schema.go index 3719293db..55da8b63b 100644 --- a/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/schema.go +++ b/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/schema.go @@ -15,7 +15,7 @@ package v1_2_exp import ( - base "github.com/coreos/butane/base/v0_6_exp" + base "github.com/coreos/butane/base/v0_7_exp" ) type Config struct { diff --git a/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/translate.go b/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/translate.go index e74b6f406..59bee14ef 100644 --- a/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/translate.go +++ b/vendor/github.com/coreos/butane/config/flatcar/v1_2_exp/translate.go @@ -18,27 +18,33 @@ import ( "github.com/coreos/butane/config/common" cutil "github.com/coreos/butane/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" "github.com/coreos/vcontext/report" ) +var ( + fieldFilters = cutil.NewFilters(types.Config{}, cutil.FilterMap{ + "storage.luks.cex": common.ErrCexNotSupported, + }) +) + // Return FieldFilters for this spec. func (c Config) FieldFilters() *cutil.FieldFilters { - return nil + return &fieldFilters } // ToIgn3_5 translates the config to an Ignition config. It returns a // report of any errors or warnings in the source and resultant config. If // the report has fatal errors or it encounters other problems translating, // an error is returned. -func (c Config) ToIgn3_5(options common.TranslateOptions) (types.Config, report.Report, error) { - cfg, r, err := cutil.Translate(c, "ToIgn3_5Unvalidated", options) +func (c Config) ToIgn3_6(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_6Unvalidated", options) return cfg.(types.Config), r, err } // ToIgn3_5Bytes translates from a v1.2 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or // warnings in the source and resultant config. If the report has fatal errors or it encounters other problems // translating, an error is returned. -func ToIgn3_5Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { - return cutil.TranslateBytes(input, &Config{}, "ToIgn3_5", options) +func ToIgn3_6Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_6", options) } diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/result/schema.go b/vendor/github.com/coreos/butane/config/openshift/v4_18/result/schema.go similarity index 95% rename from vendor/github.com/coreos/butane/config/openshift/v4_18_exp/result/schema.go rename to vendor/github.com/coreos/butane/config/openshift/v4_18/result/schema.go index c8d45b794..ad5abd8ee 100644 --- a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/result/schema.go +++ b/vendor/github.com/coreos/butane/config/openshift/v4_18/result/schema.go @@ -15,7 +15,7 @@ package result import ( - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_4/types" ) const ( diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/schema.go b/vendor/github.com/coreos/butane/config/openshift/v4_18/schema.go similarity index 94% rename from vendor/github.com/coreos/butane/config/openshift/v4_18_exp/schema.go rename to vendor/github.com/coreos/butane/config/openshift/v4_18/schema.go index b9dfbe4d5..c9da45ad3 100644 --- a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/schema.go +++ b/vendor/github.com/coreos/butane/config/openshift/v4_18/schema.go @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v4_18_exp +package v4_18 import ( - fcos "github.com/coreos/butane/config/fcos/v1_6_exp" + fcos "github.com/coreos/butane/config/fcos/v1_5" ) const ROLE_LABEL_KEY = "machineconfiguration.openshift.io/role" diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_18/translate.go b/vendor/github.com/coreos/butane/config/openshift/v4_18/translate.go new file mode 100644 index 000000000..b3d78f74d --- /dev/null +++ b/vendor/github.com/coreos/butane/config/openshift/v4_18/translate.go @@ -0,0 +1,303 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v4_18 + +import ( + "net/url" + "strings" + + "github.com/coreos/butane/config/common" + "github.com/coreos/butane/config/openshift/v4_18/result" + cutil "github.com/coreos/butane/config/util" + "github.com/coreos/butane/translate" + + "github.com/coreos/ignition/v2/config/util" + "github.com/coreos/ignition/v2/config/v3_4/types" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +// Error classes: +// +// UNPARSABLE - Cannot be rendered into a config by the MCC. If present in +// MC, MCC will mark the pool degraded. We reject these. +// +// FORBIDDEN - Not supported by the MCD. If present in MC, MCD will mark +// the node degraded. We reject these. +// +// REDUNDANT - Feature is also provided by a MachineConfig-specific field +// with different semantics. To reduce confusion, disable this +// implementation. +// +// IMMUTABLE - Permitted in MC, passed through to Ignition, but not +// supported by the MCD. MCD will mark the node degraded if the field +// changes after the node is provisioned. We reject these outright to +// discourage their use. +// +// TRIPWIRE - A subset of fields in the containing struct are supported by +// the MCD. If the struct contents change after the node is provisioned, +// and the struct contains unsupported fields, MCD will mark the node +// degraded, even if the change only affects supported fields. We reject +// these. + +const ( + // FIPS 140-2 doesn't allow the default XTS mode + fipsCipherOption = types.LuksOption("--cipher") + fipsCipherShortOption = types.LuksOption("-c") + fipsCipherArgument = types.LuksOption("aes-cbc-essiv:sha256") +) + +var ( + // See also validateRHCOSSupport() and validateMCOSupport() + fieldFilters = cutil.NewFilters(result.MachineConfig{}, cutil.FilterMap{ + // UNPARSABLE, REDUNDANT + "spec.config.kernelArguments": common.ErrKernelArgumentSupport, + // IMMUTABLE + "spec.config.passwd.groups": common.ErrGroupSupport, + // TRIPWIRE + "spec.config.passwd.users.gecos": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.groups": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.homeDir": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.noCreateHome": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.noLogInit": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.noUserGroup": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.primaryGroup": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.shell": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.shouldExist": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.system": common.ErrUserFieldSupport, + // TRIPWIRE + "spec.config.passwd.users.uid": common.ErrUserFieldSupport, + // IMMUTABLE + "spec.config.storage.directories": common.ErrDirectorySupport, + // FORBIDDEN + "spec.config.storage.files.append": common.ErrFileAppendSupport, + // redundant with a check from Ignition validation, but ensures we + // exclude the section from docs + "spec.config.storage.files.contents.httpHeaders": common.ErrFileHeaderSupport, + // IMMUTABLE + // If you change this to be less restrictive without adding + // link support in the MCO, consider what should happen if + // the user specifies a storage.tree that includes symlinks. + "spec.config.storage.links": common.ErrLinkSupport, + }) +) + +// Return FieldFilters for this spec. +func (c Config) FieldFilters() *cutil.FieldFilters { + return &fieldFilters +} + +// ToMachineConfig4_18Unvalidated translates the config to a MachineConfig. It also +// returns the set of translations it did so paths in the resultant config +// can be tracked back to their source in the source config. No config +// validation is performed on input or output. +func (c Config) ToMachineConfig4_18Unvalidated(options common.TranslateOptions) (result.MachineConfig, translate.TranslationSet, report.Report) { + cfg, ts, r := c.Config.ToIgn3_4Unvalidated(options) + if r.IsFatal() { + return result.MachineConfig{}, ts, r + } + + // wrap + ts = ts.PrefixPaths(path.New("yaml"), path.New("json", "spec", "config")) + mc := result.MachineConfig{ + ApiVersion: result.MC_API_VERSION, + Kind: result.MC_KIND, + Metadata: result.Metadata{ + Name: c.Metadata.Name, + Labels: make(map[string]string), + }, + Spec: result.Spec{ + Config: cfg, + }, + } + ts.AddTranslation(path.New("yaml", "version"), path.New("json", "apiVersion")) + ts.AddTranslation(path.New("yaml", "version"), path.New("json", "kind")) + ts.AddTranslation(path.New("yaml", "metadata"), path.New("json", "metadata")) + ts.AddTranslation(path.New("yaml", "metadata", "name"), path.New("json", "metadata", "name")) + ts.AddTranslation(path.New("yaml", "metadata", "labels"), path.New("json", "metadata", "labels")) + ts.AddTranslation(path.New("yaml", "version"), path.New("json", "spec")) + ts.AddTranslation(path.New("yaml"), path.New("json", "spec", "config")) + for k, v := range c.Metadata.Labels { + mc.Metadata.Labels[k] = v + ts.AddTranslation(path.New("yaml", "metadata", "labels", k), path.New("json", "metadata", "labels", k)) + } + + // translate OpenShift fields + tr := translate.NewTranslator("yaml", "json", options) + from := &c.OpenShift + to := &mc.Spec + ts2, r2 := translate.Prefixed(tr, "extensions", &from.Extensions, &to.Extensions) + translate.MergeP(tr, ts2, &r2, "fips", &from.FIPS, &to.FIPS) + translate.MergeP2(tr, ts2, &r2, "kernel_arguments", &from.KernelArguments, "kernelArguments", &to.KernelArguments) + translate.MergeP2(tr, ts2, &r2, "kernel_type", &from.KernelType, "kernelType", &to.KernelType) + ts.MergeP2("openshift", "spec", ts2) + r.Merge(r2) + + // apply FIPS options to LUKS volumes + ts.Merge(addLuksFipsOptions(&mc)) + + // finally, check the fully desugared config for RHCOS and MCO support + r.Merge(validateRHCOSSupport(mc)) + r.Merge(validateMCOSupport(mc)) + + return mc, ts, r +} + +// ToMachineConfig4_18 translates the config to a MachineConfig. It returns a +// report of any errors or warnings in the source and resultant config. If +// the report has fatal errors or it encounters other problems translating, +// an error is returned. +func (c Config) ToMachineConfig4_18(options common.TranslateOptions) (result.MachineConfig, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToMachineConfig4_18Unvalidated", options) + return cfg.(result.MachineConfig), r, err +} + +// ToIgn3_4Unvalidated translates the config to an Ignition config. It also +// returns the set of translations it did so paths in the resultant config +// can be tracked back to their source in the source config. No config +// validation is performed on input or output. +func (c Config) ToIgn3_4Unvalidated(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { + mc, ts, r := c.ToMachineConfig4_18Unvalidated(options) + cfg := mc.Spec.Config + + // report warnings if there are any non-empty fields in Spec (other + // than the Ignition config itself) that we're ignoring + mc.Spec.Config = types.Config{} + warnings := translate.PrefixReport(cutil.CheckForElidedFields(mc.Spec), "spec") + // translate from json space into yaml space, since the caller won't + // have enough info to do it + r.Merge(cutil.TranslateReportPaths(warnings, ts)) + + ts = ts.Descend(path.New("json", "spec", "config")) + return cfg, ts, r +} + +// ToIgn3_4 translates the config to an Ignition config. It returns a +// report of any errors or warnings in the source and resultant config. If +// the report has fatal errors or it encounters other problems translating, +// an error is returned. +func (c Config) ToIgn3_4(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_4Unvalidated", options) + return cfg.(types.Config), r, err +} + +// ToConfigBytes translates from a v4.17 Butane config to a v4.17 MachineConfig or a v3.6.0-experimental Ignition config. It returns a report of any errors or +// warnings in the source and resultant config. If the report has fatal errors or it encounters other problems +// translating, an error is returned. +func ToConfigBytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { + if options.Raw { + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_4", options) + } else { + return cutil.TranslateBytesYAML(input, &Config{}, "ToMachineConfig4_18", options) + } +} + +func addLuksFipsOptions(mc *result.MachineConfig) translate.TranslationSet { + ts := translate.NewTranslationSet("yaml", "json") + if !util.IsTrue(mc.Spec.FIPS) { + return ts + } + +OUTER: + for i := range mc.Spec.Config.Storage.Luks { + luks := &mc.Spec.Config.Storage.Luks[i] + // Only add options if the user hasn't already specified + // a cipher option. Do this in-place, since config merging + // doesn't support conditional logic. + for _, option := range luks.Options { + if option == fipsCipherOption || + strings.HasPrefix(string(option), string(fipsCipherOption)+"=") || + option == fipsCipherShortOption { + continue OUTER + } + } + for j := 0; j < 2; j++ { + ts.AddTranslation(path.New("yaml", "openshift", "fips"), path.New("json", "spec", "config", "storage", "luks", i, "options", len(luks.Options)+j)) + } + if len(luks.Options) == 0 { + ts.AddTranslation(path.New("yaml", "openshift", "fips"), path.New("json", "spec", "config", "storage", "luks", i, "options")) + } + luks.Options = append(luks.Options, fipsCipherOption, fipsCipherArgument) + } + return ts +} + +// Error on fields that are rejected by RHCOS. +// +// Some of these fields may have been generated by sugar (e.g. +// boot_device.luks), so we work in JSON (output) space and then translate +// paths back to YAML (input) space. That's also the reason we do these +// checks after translation, rather than during validation. +func validateRHCOSSupport(mc result.MachineConfig) report.Report { + var r report.Report + for i, fs := range mc.Spec.Config.Storage.Filesystems { + if fs.Format != nil && *fs.Format == "btrfs" { + // we don't ship mkfs.btrfs + r.AddOnError(path.New("json", "spec", "config", "storage", "filesystems", i, "format"), common.ErrBtrfsSupport) + } + } + return r +} + +// Error on fields that are rejected outright by the MCO, or that are +// unsupported by the MCO and we want to discourage. +// +// https://github.com/openshift/machine-config-operator/blob/d6dabadeca05/MachineConfigDaemon.md#supported-vs-unsupported-ignition-config-changes +// +// Some of these fields may have been generated by sugar (e.g. storage.trees), +// so we work in JSON (output) space and then translate paths back to YAML +// (input) space. That's also the reason we do these checks after +// translation, rather than during validation. +func validateMCOSupport(mc result.MachineConfig) report.Report { + // See also fieldFilters at the top of this file. + + var r report.Report + for i, fs := range mc.Spec.Config.Storage.Filesystems { + if fs.Format != nil && *fs.Format == "none" { + // UNPARSABLE + r.AddOnError(path.New("json", "spec", "config", "storage", "filesystems", i, "format"), common.ErrFilesystemNoneSupport) + } + } + for i, file := range mc.Spec.Config.Storage.Files { + if file.Contents.Source != nil { + fileSource, err := url.Parse(*file.Contents.Source) + // parse errors will be caught by normal config validation + if err == nil && fileSource.Scheme != "data" { + // FORBIDDEN + r.AddOnError(path.New("json", "spec", "config", "storage", "files", i, "contents", "source"), common.ErrFileSchemeSupport) + } + } + if file.Mode != nil && *file.Mode & ^0777 != 0 { + // UNPARSABLE + r.AddOnError(path.New("json", "spec", "config", "storage", "files", i, "mode"), common.ErrFileSpecialModeSupport) + } + } + for i, user := range mc.Spec.Config.Passwd.Users { + if user.Name != "core" { + // TRIPWIRE + r.AddOnError(path.New("json", "spec", "config", "passwd", "users", i, "name"), common.ErrUserNameSupport) + } + } + return r +} diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/validate.go b/vendor/github.com/coreos/butane/config/openshift/v4_18/validate.go similarity index 98% rename from vendor/github.com/coreos/butane/config/openshift/v4_18_exp/validate.go rename to vendor/github.com/coreos/butane/config/openshift/v4_18/validate.go index e8e744d00..a45ec6060 100644 --- a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/validate.go +++ b/vendor/github.com/coreos/butane/config/openshift/v4_18/validate.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v4_18_exp +package v4_18 import ( "github.com/coreos/butane/config/common" diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/result/schema.go b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/result/schema.go new file mode 100644 index 000000000..09b5b597c --- /dev/null +++ b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/result/schema.go @@ -0,0 +1,48 @@ +// Copyright 2021 Red Hat, Inc +// +// 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 result + +import ( + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" +) + +const ( + MC_API_VERSION = "machineconfiguration.openshift.io/v1" + MC_KIND = "MachineConfig" +) + +// We round-trip through JSON because Ignition uses `json` struct tags, +// so all struct tags need to be `json` even though we're ultimately +// writing YAML. + +type MachineConfig struct { + ApiVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Metadata Metadata `json:"metadata"` + Spec Spec `json:"spec"` +} + +type Metadata struct { + Name string `json:"name"` + Labels map[string]string `json:"labels,omitempty"` +} + +type Spec struct { + Config types.Config `json:"config"` + KernelArguments []string `json:"kernelArguments,omitempty"` + Extensions []string `json:"extensions,omitempty"` + FIPS *bool `json:"fips,omitempty"` + KernelType *string `json:"kernelType,omitempty"` +} diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/schema.go b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/schema.go new file mode 100644 index 000000000..5acdd04a5 --- /dev/null +++ b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/schema.go @@ -0,0 +1,39 @@ +// Copyright 2020 Red Hat, Inc +// +// 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 v4_19_exp + +import ( + fcos "github.com/coreos/butane/config/fcos/v1_7_exp" +) + +const ROLE_LABEL_KEY = "machineconfiguration.openshift.io/role" + +type Config struct { + fcos.Config `yaml:",inline"` + Metadata Metadata `yaml:"metadata"` + OpenShift OpenShift `yaml:"openshift"` +} + +type Metadata struct { + Name string `yaml:"name"` + Labels map[string]string `yaml:"labels,omitempty"` +} + +type OpenShift struct { + KernelArguments []string `yaml:"kernel_arguments"` + Extensions []string `yaml:"extensions"` + FIPS *bool `yaml:"fips"` + KernelType *string `yaml:"kernel_type"` +} diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/translate.go b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/translate.go similarity index 93% rename from vendor/github.com/coreos/butane/config/openshift/v4_18_exp/translate.go rename to vendor/github.com/coreos/butane/config/openshift/v4_19_exp/translate.go index 37612a760..e535e6127 100644 --- a/vendor/github.com/coreos/butane/config/openshift/v4_18_exp/translate.go +++ b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/translate.go @@ -12,19 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License.) -package v4_18_exp +package v4_19_exp import ( "net/url" "strings" "github.com/coreos/butane/config/common" - "github.com/coreos/butane/config/openshift/v4_18_exp/result" + "github.com/coreos/butane/config/openshift/v4_19_exp/result" cutil "github.com/coreos/butane/config/util" "github.com/coreos/butane/translate" "github.com/coreos/ignition/v2/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" "github.com/coreos/vcontext/path" "github.com/coreos/vcontext/report" ) @@ -112,8 +112,8 @@ func (c Config) FieldFilters() *cutil.FieldFilters { // returns the set of translations it did so paths in the resultant config // can be tracked back to their source in the source config. No config // validation is performed on input or output. -func (c Config) ToMachineConfig4_18Unvalidated(options common.TranslateOptions) (result.MachineConfig, translate.TranslationSet, report.Report) { - cfg, ts, r := c.Config.ToIgn3_5Unvalidated(options) +func (c Config) ToMachineConfig4_19Unvalidated(options common.TranslateOptions) (result.MachineConfig, translate.TranslationSet, report.Report) { + cfg, ts, r := c.Config.ToIgn3_6Unvalidated(options) if r.IsFatal() { return result.MachineConfig{}, ts, r } @@ -169,17 +169,17 @@ func (c Config) ToMachineConfig4_18Unvalidated(options common.TranslateOptions) // report of any errors or warnings in the source and resultant config. If // the report has fatal errors or it encounters other problems translating, // an error is returned. -func (c Config) ToMachineConfig4_18(options common.TranslateOptions) (result.MachineConfig, report.Report, error) { - cfg, r, err := cutil.Translate(c, "ToMachineConfig4_18Unvalidated", options) +func (c Config) ToMachineConfig4_19(options common.TranslateOptions) (result.MachineConfig, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToMachineConfig4_19Unvalidated", options) return cfg.(result.MachineConfig), r, err } -// ToIgn3_5Unvalidated translates the config to an Ignition config. It also +// ToIgn3_6Unvalidated translates the config to an Ignition config. It also // returns the set of translations it did so paths in the resultant config // can be tracked back to their source in the source config. No config // validation is performed on input or output. -func (c Config) ToIgn3_5Unvalidated(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { - mc, ts, r := c.ToMachineConfig4_18Unvalidated(options) +func (c Config) ToIgn3_6Unvalidated(options common.TranslateOptions) (types.Config, translate.TranslationSet, report.Report) { + mc, ts, r := c.ToMachineConfig4_19Unvalidated(options) cfg := mc.Spec.Config // report warnings if there are any non-empty fields in Spec (other @@ -194,23 +194,23 @@ func (c Config) ToIgn3_5Unvalidated(options common.TranslateOptions) (types.Conf return cfg, ts, r } -// ToIgn3_5 translates the config to an Ignition config. It returns a +// ToIgn3_6 translates the config to an Ignition config. It returns a // report of any errors or warnings in the source and resultant config. If // the report has fatal errors or it encounters other problems translating, // an error is returned. -func (c Config) ToIgn3_5(options common.TranslateOptions) (types.Config, report.Report, error) { - cfg, r, err := cutil.Translate(c, "ToIgn3_5Unvalidated", options) +func (c Config) ToIgn3_6(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_6Unvalidated", options) return cfg.(types.Config), r, err } -// ToConfigBytes translates from a v4.17 Butane config to a v4.17 MachineConfig or a v3.5.0 Ignition config. It returns a report of any errors or +// ToConfigBytes translates from a v4.17 Butane config to a v4.17 MachineConfig or a v3.6.0-experimental Ignition config. It returns a report of any errors or // warnings in the source and resultant config. If the report has fatal errors or it encounters other problems // translating, an error is returned. func ToConfigBytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { if options.Raw { - return cutil.TranslateBytes(input, &Config{}, "ToIgn3_5", options) + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_6", options) } else { - return cutil.TranslateBytesYAML(input, &Config{}, "ToMachineConfig4_18", options) + return cutil.TranslateBytesYAML(input, &Config{}, "ToMachineConfig4_19", options) } } diff --git a/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/validate.go b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/validate.go new file mode 100644 index 000000000..969bf98d4 --- /dev/null +++ b/vendor/github.com/coreos/butane/config/openshift/v4_19_exp/validate.go @@ -0,0 +1,43 @@ +// Copyright 2021 Red Hat, Inc +// +// 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 v4_19_exp + +import ( + "github.com/coreos/butane/config/common" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (m Metadata) Validate(c path.ContextPath) (r report.Report) { + if m.Name == "" { + r.AddOnError(c.Append("name"), common.ErrNameRequired) + } + if m.Labels[ROLE_LABEL_KEY] == "" { + r.AddOnError(c.Append("labels"), common.ErrRoleRequired) + } + return +} + +func (os OpenShift) Validate(c path.ContextPath) (r report.Report) { + if os.KernelType != nil { + switch *os.KernelType { + case "", "default", "realtime": + default: + r.AddOnError(c.Append("kernel_type"), common.ErrInvalidKernelType) + } + } + return +} diff --git a/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/schema.go b/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/schema.go index ffece594a..56eea4787 100644 --- a/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/schema.go +++ b/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/schema.go @@ -15,7 +15,7 @@ package v1_2_exp import ( - base "github.com/coreos/butane/base/v0_6_exp" + base "github.com/coreos/butane/base/v0_7_exp" ) type Config struct { diff --git a/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/translate.go b/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/translate.go index 1ca3ca797..cde4d4a00 100644 --- a/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/translate.go +++ b/vendor/github.com/coreos/butane/config/r4e/v1_2_exp/translate.go @@ -18,7 +18,7 @@ import ( "github.com/coreos/butane/config/common" cutil "github.com/coreos/butane/config/util" - "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/v3_6_experimental/types" "github.com/coreos/vcontext/report" ) @@ -37,18 +37,18 @@ func (c Config) FieldFilters() *cutil.FieldFilters { return &fieldFilters } -// ToIgn3_5 translates the config to an Ignition config. It returns a +// ToIgn3_6 translates the config to an Ignition config. It returns a // report of any errors or warnings in the source and resultant config. If // the report has fatal errors or it encounters other problems translating, // an error is returned. -func (c Config) ToIgn3_5(options common.TranslateOptions) (types.Config, report.Report, error) { - cfg, r, err := cutil.Translate(c, "ToIgn3_5Unvalidated", options) +func (c Config) ToIgn3_6(options common.TranslateOptions) (types.Config, report.Report, error) { + cfg, r, err := cutil.Translate(c, "ToIgn3_6Unvalidated", options) return cfg.(types.Config), r, err } -// ToIgn3_5Bytes translates from a v1.2 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or +// ToIgn3_6Bytes translates from a v1.2 Butane config to a v3.5.0 Ignition config. It returns a report of any errors or // warnings in the source and resultant config. If the report has fatal errors or it encounters other problems // translating, an error is returned. -func ToIgn3_5Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { - return cutil.TranslateBytes(input, &Config{}, "ToIgn3_5", options) +func ToIgn3_6Bytes(input []byte, options common.TranslateBytesOptions) ([]byte, report.Report, error) { + return cutil.TranslateBytes(input, &Config{}, "ToIgn3_6", options) } diff --git a/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go b/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go index 8e2d24d5e..13742ab01 100644 --- a/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go +++ b/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go @@ -85,6 +85,8 @@ var ( ErrInvalidProxy = errors.New("proxies must be http(s)") ErrInsecureProxy = errors.New("insecure plaintext HTTP proxy specified for HTTPS resources") ErrPathConflictsSystemd = errors.New("path conflicts with systemd unit or dropin") + ErrCexWithClevis = errors.New("cannot use cex with clevis") + ErrCexWithKeyFile = errors.New("cannot use key file with cex") // Systemd section errors ErrInvalidSystemdExt = errors.New("invalid systemd unit extension") diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go new file mode 100644 index 000000000..b34f5f527 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go @@ -0,0 +1,33 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (cm Cex) IsPresent() bool { + return util.IsTrue(cm.Enabled) +} + +func (cx Cex) Validate(c path.ContextPath) (r report.Report) { + if !util.IsTrue(cx.Enabled) { + return + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/clevis.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/clevis.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go new file mode 100644 index 000000000..659657b63 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go @@ -0,0 +1,64 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +var ( + MaxVersion = semver.Version{ + Major: 3, + Minor: 5, + } +) + +func (cfg Config) Validate(c path.ContextPath) (r report.Report) { + systemdPath := "/etc/systemd/system/" + unitPaths := map[string]struct{}{} + for _, unit := range cfg.Systemd.Units { + if !util.NilOrEmpty(unit.Contents) { + pathString := systemdPath + unit.Name + unitPaths[pathString] = struct{}{} + } + for _, dropin := range unit.Dropins { + if !util.NilOrEmpty(dropin.Contents) { + pathString := systemdPath + unit.Name + ".d/" + dropin.Name + unitPaths[pathString] = struct{}{} + } + } + } + for i, f := range cfg.Storage.Files { + if _, exists := unitPaths[f.Path]; exists { + r.AddOnError(c.Append("storage", "files", i, "path"), errors.ErrPathConflictsSystemd) + } + } + for i, d := range cfg.Storage.Directories { + if _, exists := unitPaths[d.Path]; exists { + r.AddOnError(c.Append("storage", "directories", i, "path"), errors.ErrPathConflictsSystemd) + } + } + for i, l := range cfg.Storage.Links { + if _, exists := unitPaths[l.Path]; exists { + r.AddOnError(c.Append("storage", "links", i, "path"), errors.ErrPathConflictsSystemd) + } + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/device.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/device.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/directory.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/directory.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/disk.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/disk.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/file.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/file.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/filesystem.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/filesystem.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/headers.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/headers.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/ignition.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/kargs.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/kargs.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/luks.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go similarity index 87% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/luks.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go index 90d723870..e4c1d6815 100644 --- a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/luks.go +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go @@ -53,6 +53,17 @@ func (l Luks) Validate(c path.ContextPath) (r report.Report) { if err := validateURLNilOK(l.KeyFile.Source); err != nil { r.AddOnError(c.Append("keys"), errors.ErrInvalidLuksKeyFile) } + + // fail if Cex use with Clevis + if l.Clevis.IsPresent() && l.Cex.IsPresent() { + r.AddOnError(c.Append("cex"), errors.ErrCexWithClevis) + } + + // fail if key file is provided along with Cex + if l.Cex.IsPresent() && util.NotEmpty(l.KeyFile.Source) { + r.AddOnError(c.Append("cex"), errors.ErrCexWithKeyFile) + } + return } diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/mode.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/mode.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/node.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/node.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/partition.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/partition.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/passwd.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/path.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/path.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/proxy.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/proxy.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/raid.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/raid.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/resource.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/resource.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go new file mode 100644 index 000000000..6c8c42f57 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go @@ -0,0 +1,264 @@ +package types + +// generated by "schematyper --package=types config/v3_5/schema/ignition.json -o config/v3_5/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Cex struct { + Enabled *bool `json:"enabled,omitempty"` +} + +type Clevis struct { + Custom ClevisCustom `json:"custom,omitempty"` + Tang []Tang `json:"tang,omitempty"` + Threshold *int `json:"threshold,omitempty"` + Tpm2 *bool `json:"tpm2,omitempty"` +} + +type ClevisCustom struct { + Config *string `json:"config,omitempty"` + NeedsNetwork *bool `json:"needsNetwork,omitempty"` + Pin *string `json:"pin,omitempty"` +} + +type Config struct { + Ignition Ignition `json:"ignition"` + KernelArguments KernelArguments `json:"kernelArguments,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode *int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable *bool `json:"wipeTable,omitempty"` +} + +type Dropin struct { + Contents *string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileEmbedded1 struct { + Append []Resource `json:"append,omitempty"` + Contents Resource `json:"contents,omitempty"` + Mode *int `json:"mode,omitempty"` +} + +type Filesystem struct { + Device string `json:"device"` + Format *string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + MountOptions []MountOption `json:"mountOptions,omitempty"` + Options []FilesystemOption `json:"options,omitempty"` + Path *string `json:"path,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem *bool `json:"wipeFilesystem,omitempty"` +} + +type FilesystemOption string + +type Group string + +type HTTPHeader struct { + Name string `json:"name"` + Value *string `json:"value,omitempty"` +} + +type HTTPHeaders []HTTPHeader + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Proxy Proxy `json:"proxy,omitempty"` + Security Security `json:"security,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version"` +} + +type IgnitionConfig struct { + Merge []Resource `json:"merge,omitempty"` + Replace Resource `json:"replace,omitempty"` +} + +type KernelArgument string + +type KernelArguments struct { + ShouldExist []KernelArgument `json:"shouldExist,omitempty"` + ShouldNotExist []KernelArgument `json:"shouldNotExist,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard *bool `json:"hard,omitempty"` + Target *string `json:"target,omitempty"` +} + +type Luks struct { + Cex Cex `json:"cex,omitempty"` + Clevis Clevis `json:"clevis,omitempty"` + Device *string `json:"device,omitempty"` + Discard *bool `json:"discard,omitempty"` + KeyFile Resource `json:"keyFile,omitempty"` + Label *string `json:"label,omitempty"` + Name string `json:"name"` + OpenOptions []OpenOption `json:"openOptions,omitempty"` + Options []LuksOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeVolume *bool `json:"wipeVolume,omitempty"` +} + +type LuksOption string + +type MountOption string + +type NoProxyItem string + +type Node struct { + Group NodeGroup `json:"group,omitempty"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path"` + User NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` +} + +type OpenOption string + +type Partition struct { + GUID *string `json:"guid,omitempty"` + Label *string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Resize *bool `json:"resize,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + SizeMiB *int `json:"sizeMiB,omitempty"` + StartMiB *int `json:"startMiB,omitempty"` + TypeGUID *string `json:"typeGuid,omitempty"` + WipePartitionEntry *bool `json:"wipePartitionEntry,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name"` + PasswordHash *string `json:"passwordHash,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + System *bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Gecos *string `json:"gecos,omitempty"` + Groups []Group `json:"groups,omitempty"` + HomeDir *string `json:"homeDir,omitempty"` + Name string `json:"name"` + NoCreateHome *bool `json:"noCreateHome,omitempty"` + NoLogInit *bool `json:"noLogInit,omitempty"` + NoUserGroup *bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup *string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell *string `json:"shell,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + System *bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type Proxy struct { + HTTPProxy *string `json:"httpProxy,omitempty"` + HTTPSProxy *string `json:"httpsProxy,omitempty"` + NoProxy []NoProxyItem `json:"noProxy,omitempty"` +} + +type Raid struct { + Devices []Device `json:"devices,omitempty"` + Level *string `json:"level,omitempty"` + Name string `json:"name"` + Options []RaidOption `json:"options,omitempty"` + Spares *int `json:"spares,omitempty"` +} + +type RaidOption string + +type Resource struct { + Compression *string `json:"compression,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source *string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type SSHAuthorizedKey string + +type Security struct { + TLS TLS `json:"tls,omitempty"` +} + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Luks []Luks `json:"luks,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type TLS struct { + CertificateAuthorities []Resource `json:"certificateAuthorities,omitempty"` +} + +type Tang struct { + Advertisement *string `json:"advertisement,omitempty"` + Thumbprint *string `json:"thumbprint,omitempty"` + URL string `json:"url,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents *string `json:"contents,omitempty"` + Dropins []Dropin `json:"dropins,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask *bool `json:"mask,omitempty"` + Name string `json:"name"` +} + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/storage.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/storage.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/systemd.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/systemd.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/tang.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/tang.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/tls.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/tls.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/unit.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/unit.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/url.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/url.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/verification.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go similarity index 100% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/verification.go rename to vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/cex.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/cex.go new file mode 100644 index 000000000..b34f5f527 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/cex.go @@ -0,0 +1,33 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (cm Cex) IsPresent() bool { + return util.IsTrue(cm.Enabled) +} + +func (cx Cex) Validate(c path.ContextPath) (r report.Report) { + if !util.IsTrue(cx.Enabled) { + return + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/clevis.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/clevis.go new file mode 100644 index 000000000..68887d434 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/clevis.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (c Clevis) IsPresent() bool { + return util.NotEmpty(c.Custom.Pin) || + len(c.Tang) > 0 || + util.IsTrue(c.Tpm2) || + c.Threshold != nil && *c.Threshold != 0 +} + +func (cu ClevisCustom) Validate(c path.ContextPath) (r report.Report) { + if util.NilOrEmpty(cu.Pin) && util.NilOrEmpty(cu.Config) && !util.IsTrue(cu.NeedsNetwork) { + return + } + if util.NotEmpty(cu.Pin) { + switch *cu.Pin { + case "tpm2", "tang", "sss": + default: + r.AddOnError(c.Append("pin"), errors.ErrUnknownClevisPin) + } + } else { + r.AddOnError(c.Append("pin"), errors.ErrClevisPinRequired) + } + if util.NilOrEmpty(cu.Config) { + r.AddOnError(c.Append("config"), errors.ErrClevisConfigRequired) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/config.go similarity index 99% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/config.go rename to vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/config.go index 40c27106e..9428b0bb2 100644 --- a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/config.go +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/config.go @@ -26,7 +26,7 @@ import ( var ( MaxVersion = semver.Version{ Major: 3, - Minor: 5, + Minor: 6, PreRelease: "experimental", } ) diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/device.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/device.go new file mode 100644 index 000000000..a10ce97b0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/device.go @@ -0,0 +1,25 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Device) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c, validatePath(string(d))) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/directory.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/directory.go new file mode 100644 index 000000000..f6f068455 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/directory.go @@ -0,0 +1,26 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Directory) Validate(c path.ContextPath) (r report.Report) { + r.Merge(d.Node.Validate(c)) + r.AddOnError(c.Append("mode"), validateMode(d.Mode)) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/disk.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/disk.go new file mode 100644 index 000000000..8caf8499d --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/disk.go @@ -0,0 +1,135 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Disk) Key() string { + return d.Device +} + +func (n Disk) Validate(c path.ContextPath) (r report.Report) { + if len(n.Device) == 0 { + r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) + return + } + r.AddOnError(c.Append("device"), validatePath(n.Device)) + + if collides, p := n.partitionNumbersCollide(); collides { + r.AddOnError(c.Append("partitions", p), errors.ErrPartitionNumbersCollide) + } + if overlaps, p := n.partitionsOverlap(); overlaps { + r.AddOnError(c.Append("partitions", p), errors.ErrPartitionsOverlap) + } + if n.partitionsMixZeroesAndNonexistence() { + r.AddOnError(c.Append("partitions"), errors.ErrZeroesWithShouldNotExist) + } + if collides, p := n.partitionLabelsCollide(); collides { + r.AddOnError(c.Append("partitions", p), errors.ErrDuplicateLabels) + } + return +} + +// partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. It also returns the +// index of the colliding partition +func (n Disk) partitionNumbersCollide() (bool, int) { + m := map[int][]int{} // from partition number to index into array + for i, p := range n.Partitions { + if p.Number != 0 { + // a number of 0 means next available number, multiple devices can specify this + m[p.Number] = append(m[p.Number], i) + } + } + for _, n := range m { + if len(n) > 1 { + // TODO(vc): return information describing the collision for logging + return true, n[1] + } + } + return false, 0 +} + +func (d Disk) partitionLabelsCollide() (bool, int) { + m := map[string]struct{}{} + for i, p := range d.Partitions { + if p.Label != nil { + // a number of 0 means next available number, multiple devices can specify this + if _, exists := m[*p.Label]; exists { + return true, i + } + m[*p.Label] = struct{}{} + } + } + return false, 0 +} + +// end returns the last sector of a partition. Only used by partitionsOverlap. Requires non-nil Start and Size. +func (p Partition) end() int { + if *p.SizeMiB == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return *p.StartMiB + } + return *p.StartMiB + *p.SizeMiB - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap. It also returns the index of +// the overlapping partition +func (n Disk) partitionsOverlap() (bool, int) { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.StartMiB == nil || p.SizeMiB == nil || *p.StartMiB == 0 { + continue + } + + for i, o := range n.Partitions { + if o.StartMiB == nil || o.SizeMiB == nil || p == o || *o.StartMiB == 0 { + continue + } + + // is p.StartMiB within o? + if *p.StartMiB >= *o.StartMiB && *p.StartMiB <= o.end() { + return true, i + } + + // is p.end() within o? + if p.end() >= *o.StartMiB && p.end() <= o.end() { + return true, i + } + + // do p.StartMiB and p.end() straddle o? + if *p.StartMiB < *o.StartMiB && p.end() > o.end() { + return true, i + } + } + } + return false, 0 +} + +func (n Disk) partitionsMixZeroesAndNonexistence() bool { + hasZero := false + hasShouldNotExist := false + for _, p := range n.Partitions { + hasShouldNotExist = hasShouldNotExist || util.IsFalse(p.ShouldExist) + hasZero = hasZero || (p.Number == 0) + } + return hasZero && hasShouldNotExist +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/file.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/file.go new file mode 100644 index 000000000..9b71bb26a --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/file.go @@ -0,0 +1,43 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (f File) Validate(c path.ContextPath) (r report.Report) { + r.Merge(f.Node.Validate(c)) + r.AddOnError(c.Append("mode"), validateMode(f.Mode)) + r.AddOnError(c.Append("overwrite"), f.validateOverwrite()) + return +} + +func (f File) validateOverwrite() error { + if util.IsTrue(f.Overwrite) && f.Contents.Source == nil { + return errors.ErrOverwriteAndNilSource + } + return nil +} + +func (f FileEmbedded1) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Append": {}, + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/filesystem.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/filesystem.go new file mode 100644 index 000000000..c722b3633 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/filesystem.go @@ -0,0 +1,106 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (f Filesystem) Key() string { + return f.Device +} + +func (f Filesystem) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + "MountOptions": {}, + } +} + +func (f Filesystem) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("path"), f.validatePath()) + r.AddOnError(c.Append("device"), validatePath(f.Device)) + r.AddOnError(c.Append("format"), f.validateFormat()) + r.AddOnError(c.Append("label"), f.validateLabel()) + return +} + +func (f Filesystem) validatePath() error { + return validatePathNilOK(f.Path) +} + +func (f Filesystem) validateFormat() error { + if util.NilOrEmpty(f.Format) { + if util.NotEmpty(f.Path) || + util.NotEmpty(f.Label) || + util.NotEmpty(f.UUID) || + util.IsTrue(f.WipeFilesystem) || + len(f.MountOptions) != 0 || + len(f.Options) != 0 { + return errors.ErrFormatNilWithOthers + } + } else { + switch *f.Format { + case "ext4", "btrfs", "xfs", "swap", "vfat", "none": + default: + return errors.ErrFilesystemInvalidFormat + } + } + return nil +} + +func (f Filesystem) validateLabel() error { + if util.NilOrEmpty(f.Label) { + return nil + } + if util.NilOrEmpty(f.Format) { + return errors.ErrLabelNeedsFormat + } + + switch *f.Format { + case "ext4": + if len(*f.Label) > 16 { + // source: man mkfs.ext4 + return errors.ErrExt4LabelTooLong + } + case "btrfs": + if len(*f.Label) > 256 { + // source: man mkfs.btrfs + return errors.ErrBtrfsLabelTooLong + } + case "xfs": + if len(*f.Label) > 12 { + // source: man mkfs.xfs + return errors.ErrXfsLabelTooLong + } + case "swap": + // mkswap's man page does not state a limit on label size, but through + // experimentation it appears that mkswap will truncate long labels to + // 15 characters, so let's enforce that. + if len(*f.Label) > 15 { + return errors.ErrSwapLabelTooLong + } + case "vfat": + if len(*f.Label) > 11 { + // source: man mkfs.fat + return errors.ErrVfatLabelTooLong + } + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/headers.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/headers.go new file mode 100644 index 000000000..be1aadad9 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/headers.go @@ -0,0 +1,65 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/http" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +// Parse generates standard net/http headers from the data in HTTPHeaders +func (hs HTTPHeaders) Parse() (http.Header, error) { + headers := http.Header{} + for _, header := range hs { + if header.Name == "" { + return nil, errors.ErrEmptyHTTPHeaderName + } + if header.Value == nil || string(*header.Value) == "" { + return nil, errors.ErrInvalidHTTPHeader + } + headers.Add(header.Name, string(*header.Value)) + } + return headers, nil +} + +func (h HTTPHeader) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("name"), h.validateName()) + r.AddOnError(c.Append("value"), h.validateValue()) + return +} + +func (h HTTPHeader) validateName() error { + if h.Name == "" { + return errors.ErrEmptyHTTPHeaderName + } + return nil +} + +func (h HTTPHeader) validateValue() error { + if h.Value == nil { + return nil + } + if string(*h.Value) == "" { + return errors.ErrInvalidHTTPHeader + } + return nil +} + +func (h HTTPHeader) Key() string { + return h.Name +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/ignition.go new file mode 100644 index 000000000..190445bda --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/ignition.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/go-semver/semver" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (v Ignition) Semver() (*semver.Version, error) { + return semver.NewVersion(v.Version) +} + +func (ic IgnitionConfig) Validate(c path.ContextPath) (r report.Report) { + for i, res := range ic.Merge { + r.AddOnError(c.Append("merge", i), res.validateRequiredSource()) + } + return +} + +func (v Ignition) Validate(c path.ContextPath) (r report.Report) { + c = c.Append("version") + tv, err := v.Semver() + if err != nil { + r.AddOnError(c, errors.ErrInvalidVersion) + return + } + + if MaxVersion != *tv { + r.AddOnError(c, errors.ErrUnknownVersion) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/kargs.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/kargs.go new file mode 100644 index 000000000..42c29408e --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/kargs.go @@ -0,0 +1,22 @@ +// Copyright 2021 Red Hat, Inc. +// +// 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 types + +func (k KernelArguments) MergedKeys() map[string]string { + return map[string]string{ + "ShouldExist": "KernelArgument", + "ShouldNotExist": "KernelArgument", + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/luks.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/luks.go new file mode 100644 index 000000000..e4c1d6815 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/luks.go @@ -0,0 +1,82 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (l Luks) Key() string { + return l.Name +} + +func (l Luks) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + } +} + +func (l Luks) Validate(c path.ContextPath) (r report.Report) { + if strings.Contains(l.Name, "/") { + r.AddOnError(c.Append("name"), errors.ErrLuksNameContainsSlash) + } + r.AddOnError(c.Append("label"), l.validateLabel()) + if util.NilOrEmpty(l.Device) { + r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) + } else { + r.AddOnError(c.Append("device"), validatePath(*l.Device)) + } + + if util.NotEmpty(l.Clevis.Custom.Pin) && (len(l.Clevis.Tang) > 0 || util.IsTrue(l.Clevis.Tpm2) || (l.Clevis.Threshold != nil && *l.Clevis.Threshold != 0)) { + r.AddOnError(c.Append("clevis"), errors.ErrClevisCustomWithOthers) + } + + // fail if a key file is provided and is not valid + if err := validateURLNilOK(l.KeyFile.Source); err != nil { + r.AddOnError(c.Append("keys"), errors.ErrInvalidLuksKeyFile) + } + + // fail if Cex use with Clevis + if l.Clevis.IsPresent() && l.Cex.IsPresent() { + r.AddOnError(c.Append("cex"), errors.ErrCexWithClevis) + } + + // fail if key file is provided along with Cex + if l.Cex.IsPresent() && util.NotEmpty(l.KeyFile.Source) { + r.AddOnError(c.Append("cex"), errors.ErrCexWithKeyFile) + } + + return +} + +func (l Luks) validateLabel() error { + if util.NilOrEmpty(l.Label) { + return nil + } + + if len(*l.Label) > 47 { + // LUKS2_LABEL_L has a maximum length of 48 (including the null terminator) + // https://gitlab.com/cryptsetup/cryptsetup/-/blob/1633f030e89ad2f11ae649ba9600997a41abd3fc/lib/luks2/luks2.h#L86 + return errors.ErrLuksLabelTooLong + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/mode.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/mode.go new file mode 100644 index 000000000..9eb7573d8 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/mode.go @@ -0,0 +1,26 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" +) + +func validateMode(m *int) error { + if m != nil && (*m < 0 || *m > 07777) { + return errors.ErrFileIllegalMode + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/node.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/node.go new file mode 100644 index 000000000..248276e73 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/node.go @@ -0,0 +1,59 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (n Node) Key() string { + return n.Path +} + +func (n Node) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c.Append("path"), validatePath(n.Path)) + return +} + +func (n Node) Depth() int { + count := 0 + for p := path.Clean(string(n.Path)); p != "/"; count++ { + p = path.Dir(p) + } + return count +} + +func validateIDorName(id *int, name *string) error { + if id != nil && util.NotEmpty(name) { + return errors.ErrBothIDAndNameSet + } + return nil +} + +func (nu NodeUser) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c, validateIDorName(nu.ID, nu.Name)) + return +} + +func (ng NodeGroup) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c, validateIDorName(ng.ID, ng.Name)) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/partition.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/partition.go new file mode 100644 index 000000000..1b2d97edf --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/partition.go @@ -0,0 +1,91 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "fmt" + "regexp" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) + +var ( + guidRegex = regexp.MustCompile(guidRegexStr) +) + +func (p Partition) Key() string { + if p.Number != 0 { + return fmt.Sprintf("number:%d", p.Number) + } else if p.Label != nil { + return fmt.Sprintf("label:%s", *p.Label) + } else { + return "" + } +} + +func (p Partition) Validate(c path.ContextPath) (r report.Report) { + if util.IsFalse(p.ShouldExist) && + (p.Label != nil || util.NotEmpty(p.TypeGUID) || util.NotEmpty(p.GUID) || p.StartMiB != nil || p.SizeMiB != nil) { + r.AddOnError(c, errors.ErrShouldNotExistWithOthers) + } + if p.Number == 0 && p.Label == nil { + r.AddOnError(c, errors.ErrNeedLabelOrNumber) + } + + r.AddOnError(c.Append("label"), p.validateLabel()) + r.AddOnError(c.Append("guid"), validateGUID(p.GUID)) + r.AddOnError(c.Append("typeGuid"), validateGUID(p.TypeGUID)) + return +} + +func (p Partition) validateLabel() error { + if p.Label == nil { + return nil + } + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(*p.Label) > 36 { + return errors.ErrLabelTooLong + } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(*p.Label, ":") { + return errors.ErrLabelContainsColon + } + return nil +} + +func validateGUID(guidPointer *string) error { + if guidPointer == nil { + return nil + } + guid := *guidPointer + if ok := guidRegex.MatchString(guid); !ok { + return errors.ErrDoesntMatchGUIDRegex + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/passwd.go new file mode 100644 index 000000000..4060a2a6f --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/passwd.go @@ -0,0 +1,23 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +func (p PasswdUser) Key() string { + return p.Name +} + +func (g PasswdGroup) Key() string { + return g.Name +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/path.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/path.go new file mode 100644 index 000000000..131e300c1 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/path.go @@ -0,0 +1,42 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" +) + +func validatePath(p string) error { + if p == "" { + return errors.ErrNoPath + } + if !path.IsAbs(p) { + return errors.ErrPathRelative + } + if path.Clean(p) != p { + return errors.ErrDirtyPath + } + return nil +} + +func validatePathNilOK(p *string) error { + if util.NilOrEmpty(p) { + return nil + } + return validatePath(*p) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/proxy.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/proxy.go new file mode 100644 index 000000000..d48d210a0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/proxy.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (p Proxy) Validate(c path.ContextPath) (r report.Report) { + validateProxyURL(p.HTTPProxy, c.Append("httpProxy"), &r, true) + validateProxyURL(p.HTTPSProxy, c.Append("httpsProxy"), &r, false) + return +} + +func validateProxyURL(s *string, p path.ContextPath, r *report.Report, httpOk bool) { + if s == nil { + return + } + u, err := url.Parse(*s) + if err != nil { + r.AddOnError(p, errors.ErrInvalidUrl) + return + } + + if u.Scheme != "https" && u.Scheme != "http" { + r.AddOnError(p, errors.ErrInvalidProxy) + return + } + if u.Scheme == "http" && !httpOk { + r.AddOnWarn(p, errors.ErrInsecureProxy) + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/raid.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/raid.go new file mode 100644 index 000000000..9d69aa366 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/raid.go @@ -0,0 +1,62 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (r Raid) Key() string { + return r.Name +} + +func (r Raid) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + } +} + +func (ra Raid) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("level"), ra.validateLevel()) + if len(ra.Devices) == 0 { + r.AddOnError(c.Append("devices"), errors.ErrRaidDevicesRequired) + } + return +} + +func (r Raid) validateLevel() error { + if util.NilOrEmpty(r.Level) { + return errors.ErrRaidLevelRequired + } + switch *r.Level { + case "linear", "raid0", "0", "stripe": + if r.Spares != nil && *r.Spares != 0 { + return errors.ErrSparesUnsupportedForLevel + } + case "raid1", "1", "mirror": + case "raid4", "4": + case "raid5", "5": + case "raid6", "6": + case "raid10", "10": + default: + return errors.ErrUnrecognizedRaidLevel + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/resource.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/resource.go new file mode 100644 index 000000000..68da6c7b7 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/resource.go @@ -0,0 +1,91 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (res Resource) Key() string { + if res.Source == nil { + return "" + } + return *res.Source +} + +func (res Resource) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("compression"), res.validateCompression()) + r.AddOnError(c.Append("verification", "hash"), res.validateVerification()) + r.AddOnError(c.Append("source"), validateURLNilOK(res.Source)) + r.AddOnError(c.Append("httpHeaders"), res.validateSchemeForHTTPHeaders()) + return +} + +func (res Resource) validateCompression() error { + if res.Compression != nil { + switch *res.Compression { + case "", "gzip": + default: + return errors.ErrCompressionInvalid + } + } + return nil +} + +func (res Resource) validateVerification() error { + if res.Verification.Hash != nil && res.Source == nil { + return errors.ErrVerificationAndNilSource + } + return nil +} + +func (res Resource) validateSchemeForHTTPHeaders() error { + if len(res.HTTPHeaders) < 1 { + return nil + } + + if util.NilOrEmpty(res.Source) { + return errors.ErrInvalidUrl + } + + u, err := url.Parse(*res.Source) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https": + return nil + default: + return errors.ErrUnsupportedSchemeForHTTPHeaders + } +} + +// Ensure that the Source is specified and valid. This is not called by +// Resource.Validate() because some structs that embed Resource don't +// require Source to be specified. Containing structs that require Source +// should call this function from their Validate(). +func (res Resource) validateRequiredSource() error { + if util.NilOrEmpty(res.Source) { + return errors.ErrSourceRequired + } + return validateURL(*res.Source) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/schema.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/schema.go similarity index 96% rename from vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/schema.go rename to vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/schema.go index 27fe5b5b2..c652d666d 100644 --- a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/types/schema.go +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/schema.go @@ -1,6 +1,10 @@ package types -// generated by "schematyper --package=types config/v3_5_experimental/schema/ignition.json -o config/v3_5_experimental/types/schema.go --root-type=Config" -- DO NOT EDIT +// generated by "schematyper --package=types config/v3_6_experimental/schema/ignition.json -o config/v3_6_experimental/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Cex struct { + Enabled *bool `json:"enabled,omitempty"` +} type Clevis struct { Custom ClevisCustom `json:"custom,omitempty"` @@ -109,6 +113,7 @@ type LinkEmbedded1 struct { } type Luks struct { + Cex Cex `json:"cex,omitempty"` Clevis Clevis `json:"clevis,omitempty"` Device *string `json:"device,omitempty"` Discard *bool `json:"discard,omitempty"` diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/storage.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/storage.go new file mode 100644 index 000000000..20cb73048 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/storage.go @@ -0,0 +1,115 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (s Storage) MergedKeys() map[string]string { + return map[string]string{ + "Directories": "Node", + "Files": "Node", + "Links": "Node", + } +} + +func (s Storage) Validate(c vpath.ContextPath) (r report.Report) { + s.validateDirectories(c, &r) + s.validateFiles(c, &r) + s.validateLinks(c, &r) + s.validateFilesystems(c, &r) + return +} + +func (s Storage) validateDirectories(c vpath.ContextPath, r *report.Report) { + for i, d := range s.Directories { + for _, l := range s.Links { + if strings.HasPrefix(d.Path, l.Path+"/") { + r.AddOnError(c.Append("directories", i), errors.ErrDirectoryUsedSymlink) + } + } + } +} + +func (s Storage) validateFiles(c vpath.ContextPath, r *report.Report) { + for i, f := range s.Files { + for _, l := range s.Links { + if strings.HasPrefix(f.Path, l.Path+"/") { + r.AddOnError(c.Append("files", i), errors.ErrFileUsedSymlink) + } + } + } +} + +func (s Storage) validateLinks(c vpath.ContextPath, r *report.Report) { + for i, l1 := range s.Links { + for _, l2 := range s.Links { + if strings.HasPrefix(l1.Path, l2.Path+"/") { + r.AddOnError(c.Append("links", i), errors.ErrLinkUsedSymlink) + } + } + if util.NilOrEmpty(l1.Target) { + r.AddOnError(c.Append("links", i, "target"), errors.ErrLinkTargetRequired) + continue + } + if !util.IsTrue(l1.Hard) { + continue + } + target := path.Clean(*l1.Target) + if !path.IsAbs(target) { + target = path.Join(l1.Path, *l1.Target) + } + for _, d := range s.Directories { + if target == d.Path { + r.AddOnError(c.Append("links", i), errors.ErrHardLinkToDirectory) + } + } + ownerCheck := func(ok bool, path vpath.ContextPath) { + if !ok { + r.AddOnWarn(path, errors.ErrHardLinkSpecifiesOwner) + } + } + ownerCheck(l1.User.ID == nil, c.Append("links", i, "user", "id")) + ownerCheck(l1.User.Name == nil, c.Append("links", i, "user", "name")) + ownerCheck(l1.Group.ID == nil, c.Append("links", i, "group", "id")) + ownerCheck(l1.Group.Name == nil, c.Append("links", i, "group", "name")) + } +} + +func (s Storage) validateFilesystems(c vpath.ContextPath, r *report.Report) { + disks := make(map[string]Disk) + for _, d := range s.Disks { + disks[d.Device] = d + } + + for i, f := range s.Filesystems { + disk, exist := disks[f.Device] + if exist { + if len(disk.Partitions) > 0 { + r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrPartitionsOverwritten) + } else if !util.IsTrue(f.WipeFilesystem) && util.IsTrue(disk.WipeTable) { + r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrFilesystemImplicitWipe) + } + } + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/systemd.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/systemd.go new file mode 100644 index 000000000..ac521ba73 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/systemd.go @@ -0,0 +1,61 @@ +// Copyright 2022 Red Hat, Inc. +// +// 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 types + +import ( + "regexp" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/shared/parse" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (s Systemd) Validate(c vpath.ContextPath) (r report.Report) { + units := make(map[string]Unit) + checkInstanceUnit := regexp.MustCompile(`^(.+?)@(.+?)\.service$`) + for _, d := range s.Units { + units[d.Name] = d + } + for index, unit := range s.Units { + if checkInstanceUnit.MatchString(unit.Name) && util.IsTrue(unit.Enabled) { + instUnitSlice := checkInstanceUnit.FindSubmatch([]byte(unit.Name)) + instantiableUnit := string(instUnitSlice[1]) + "@.service" + if _, ok := units[instantiableUnit]; ok && util.NotEmpty(units[instantiableUnit].Contents) { + foundInstallSection := false + // we're doing a separate validation pass on each unit to identify + // if an instantiable unit has the install section. So logging an + // `AddOnError` will produce duplicate errors on bad unit contents + // because we're already doing that while validating a unit separately. + opts, err := parse.ParseUnitContents(units[instantiableUnit].Contents) + if err != nil { + continue + } + for _, section := range opts { + if section.Section == "Install" { + foundInstallSection = true + break + } + } + if !foundInstallSection { + r.AddOnWarn(c.Append("units", index, "contents"), errors.NewNoInstallSectionForInstantiableUnitError(instantiableUnit, unit.Name)) + } + } + } + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tang.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tang.go new file mode 100644 index 000000000..1839d6cc3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tang.go @@ -0,0 +1,65 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "encoding/json" + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (t Tang) Key() string { + return t.URL +} + +func (t Tang) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("url"), validateTangURL(t.URL)) + if util.NilOrEmpty(t.Thumbprint) { + r.AddOnError(c.Append("thumbprint"), errors.ErrTangThumbprintRequired) + } + r.AddOnError(c.Append("advertisement"), validateTangAdvertisement(t.Advertisement)) + return +} + +func validateTangURL(s string) error { + u, err := url.Parse(s) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https": + return nil + default: + return errors.ErrInvalidScheme + } +} + +func validateTangAdvertisement(s *string) error { + if util.NotEmpty(s) { + var adv any + err := json.Unmarshal([]byte(*s), &adv) + if err != nil { + return errors.ErrInvalidTangAdvertisement + } + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tls.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tls.go new file mode 100644 index 000000000..8890e397e --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/tls.go @@ -0,0 +1,27 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (tls TLS) Validate(c path.ContextPath) (r report.Report) { + for i, ca := range tls.CertificateAuthorities { + r.AddOnError(c.Append("certificateAuthorities", i), ca.validateRequiredSource()) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/unit.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/unit.go new file mode 100644 index 000000000..c5ee1e8e3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/unit.go @@ -0,0 +1,68 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/shared/parse" + "github.com/coreos/ignition/v2/config/shared/validations" + "github.com/coreos/ignition/v2/config/util" + + cpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (u Unit) Key() string { + return u.Name +} + +func (d Dropin) Key() string { + return d.Name +} + +func (u Unit) Validate(c cpath.ContextPath) (r report.Report) { + r.AddOnError(c.Append("name"), validateName(u.Name)) + c = c.Append("contents") + opts, err := parse.ParseUnitContents(u.Contents) + r.AddOnError(c, err) + + r.AddOnWarn(c, validations.ValidateInstallSection(u.Name, util.IsTrue(u.Enabled), util.NilOrEmpty(u.Contents), opts)) + + return +} + +func validateName(name string) error { + switch path.Ext(name) { + case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": + default: + return errors.ErrInvalidSystemdExt + } + return nil +} + +func (d Dropin) Validate(c cpath.ContextPath) (r report.Report) { + _, err := parse.ParseUnitContents(d.Contents) + r.AddOnError(c.Append("contents"), err) + + switch path.Ext(d.Name) { + case ".conf": + default: + r.AddOnError(c.Append("name"), errors.ErrInvalidSystemdDropinExt) + } + + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/url.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/url.go new file mode 100644 index 000000000..3ca189dae --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/url.go @@ -0,0 +1,83 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + "strings" + + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/vincent-petithory/dataurl" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" +) + +func validateURL(s string) error { + u, err := url.Parse(s) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https", "tftp", "gs": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "arn": + fullURL := u.Scheme + ":" + u.Opaque + if !arn.IsARN(fullURL) { + return errors.ErrInvalidS3ARN + } + s3arn, err := arn.Parse(fullURL) + if err != nil { + return err + } + if s3arn.Service != "s3" { + return errors.ErrInvalidS3ARN + } + urlSplit := strings.Split(fullURL, "/") + if strings.HasPrefix(s3arn.Resource, "accesspoint/") && len(urlSplit) < 3 { + return errors.ErrInvalidS3ARN + } else if len(urlSplit) < 2 { + return errors.ErrInvalidS3ARN + } + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "data": + if _, err := dataurl.DecodeString(s); err != nil { + return err + } + return nil + default: + return errors.ErrInvalidScheme + } +} + +func validateURLNilOK(s *string) error { + if util.NilOrEmpty(s) { + return nil + } + return validateURL(*s) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/verification.go b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/verification.go new file mode 100644 index 000000000..5def6f04b --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_6_experimental/types/verification.go @@ -0,0 +1,71 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "crypto" + "encoding/hex" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +// HashParts will return the sum and function (in that order) of the hash stored +// in this Verification, or an error if there is an issue during parsing. +func (v Verification) HashParts() (string, string, error) { + if v.Hash == nil { + // The hash can be nil + return "", "", nil + } + parts := strings.SplitN(*v.Hash, "-", 2) + if len(parts) != 2 { + return "", "", errors.ErrHashMalformed + } + + return parts[0], parts[1], nil +} + +func (v Verification) Validate(c path.ContextPath) (r report.Report) { + c = c.Append("hash") + if v.Hash == nil { + // The hash can be nil + return + } + + function, sum, err := v.HashParts() + if err != nil { + r.AddOnError(c, err) + return + } + var hash crypto.Hash + switch function { + case "sha512": + hash = crypto.SHA512 + case "sha256": + hash = crypto.SHA256 + default: + r.AddOnError(c, errors.ErrHashUnrecognized) + return + } + + if len(sum) != hex.EncodedLen(hash.Size()) { + r.AddOnError(c, errors.ErrHashWrongSize) + } + + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 09189aa9d..d937c9c6a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -564,7 +564,7 @@ github.com/containers/storage/pkg/tarlog github.com/containers/storage/pkg/truncindex github.com/containers/storage/pkg/unshare github.com/containers/storage/types -# github.com/coreos/butane v0.22.0 +# github.com/coreos/butane v0.23.0 ## explicit; go 1.20 github.com/coreos/butane/base/util github.com/coreos/butane/base/v0_1 @@ -572,7 +572,8 @@ github.com/coreos/butane/base/v0_2 github.com/coreos/butane/base/v0_3 github.com/coreos/butane/base/v0_4 github.com/coreos/butane/base/v0_5 -github.com/coreos/butane/base/v0_6_exp +github.com/coreos/butane/base/v0_6 +github.com/coreos/butane/base/v0_7_exp github.com/coreos/butane/config github.com/coreos/butane/config/common github.com/coreos/butane/config/fcos/v1_0 @@ -581,7 +582,8 @@ github.com/coreos/butane/config/fcos/v1_2 github.com/coreos/butane/config/fcos/v1_3 github.com/coreos/butane/config/fcos/v1_4 github.com/coreos/butane/config/fcos/v1_5 -github.com/coreos/butane/config/fcos/v1_6_exp +github.com/coreos/butane/config/fcos/v1_6 +github.com/coreos/butane/config/fcos/v1_7_exp github.com/coreos/butane/config/fiot/v1_0 github.com/coreos/butane/config/fiot/v1_1_exp github.com/coreos/butane/config/flatcar/v1_0 @@ -603,8 +605,10 @@ github.com/coreos/butane/config/openshift/v4_16 github.com/coreos/butane/config/openshift/v4_16/result github.com/coreos/butane/config/openshift/v4_17 github.com/coreos/butane/config/openshift/v4_17/result -github.com/coreos/butane/config/openshift/v4_18_exp -github.com/coreos/butane/config/openshift/v4_18_exp/result +github.com/coreos/butane/config/openshift/v4_18 +github.com/coreos/butane/config/openshift/v4_18/result +github.com/coreos/butane/config/openshift/v4_19_exp +github.com/coreos/butane/config/openshift/v4_19_exp/result github.com/coreos/butane/config/openshift/v4_8 github.com/coreos/butane/config/openshift/v4_8/result github.com/coreos/butane/config/openshift/v4_9 @@ -623,7 +627,7 @@ github.com/coreos/go-semver/semver # github.com/coreos/go-systemd/v22 v22.5.0 ## explicit; go 1.12 github.com/coreos/go-systemd/v22/unit -# github.com/coreos/ignition/v2 v2.18.0 +# github.com/coreos/ignition/v2 v2.20.0 ## explicit; go 1.20 github.com/coreos/ignition/v2/config/merge github.com/coreos/ignition/v2/config/shared/errors @@ -635,7 +639,8 @@ github.com/coreos/ignition/v2/config/v3_1/types github.com/coreos/ignition/v2/config/v3_2/types github.com/coreos/ignition/v2/config/v3_3/types github.com/coreos/ignition/v2/config/v3_4/types -github.com/coreos/ignition/v2/config/v3_5_experimental/types +github.com/coreos/ignition/v2/config/v3_5/types +github.com/coreos/ignition/v2/config/v3_6_experimental/types github.com/coreos/ignition/v2/config/validate # github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 ## explicit; go 1.18