Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ nav_order: 9

### Features
- The name for custom clevis pins is not validated by Ignition anymore, enabling the use of arbitrary custom pins.
- Azure images can opt into `--generate-cloud-config=azure`, letting `ignition-fetch.service` synthesize an admin-user config from IMDS metadata and the provisioning media.

### Changes

Expand Down
22 changes: 21 additions & 1 deletion dracut/30ignition/ignition-generator
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,24 @@ else
fi
fi

echo "PLATFORM_ID=$(cmdline_arg ignition.platform.id)" > /run/ignition.env
platform_id="$(cmdline_arg ignition.platform.id)"
ignition_args=()

# Check if cloud config generation is requested via kernel cmdline
# Usage: ignition.config.generate=azure
generate_config="$(cmdline_arg ignition.config.generate)"
if [[ -n "${generate_config}" ]]; then
# Basic validation to prevent command injection. The value should be a
# simple platform identifier.
if [[ "${generate_config}" =~ ^[a-zA-Z0-9_-]+$ ]]; then
ignition_args+=("--generate-cloud-config=${generate_config}")
else
# Log to stderr, which is redirected to kmsg
echo "ignition-generator: invalid value for ignition.config.generate: ${generate_config}" >&2
fi
fi

{
echo "PLATFORM_ID=${platform_id}"
echo "IGNITION_ARGS=${ignition_args[*]}"
} > /run/ignition.env
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
cloud.google.com/go/storage v1.57.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
github.com/aws/aws-sdk-go-v2 v1.39.3
github.com/aws/aws-sdk-go-v2/credentials v1.18.17
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.10
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 h1:IEjq88XO4PuBDcvmjQJcQGg+w+UaafSy8G5Kcb5tBhI=
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1emQJAw5tHOaUDyY1ycttqBAPcxuzf7QbY6ec=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 h1:owcC2UnmsZycprQ5RfRgjydWhuoxg71LUfyiQdijZuM=
Expand Down
46 changes: 38 additions & 8 deletions internal/exec/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,15 @@ var (

// Engine represents the entity that fetches and executes a configuration.
type Engine struct {
ConfigCache string
FetchTimeout time.Duration
Logger *log.Logger
NeedNet string
Root string
PlatformConfig platform.Config
Fetcher *resource.Fetcher
State *state.State
ConfigCache string
FetchTimeout time.Duration
GenerateCloudConfig string
Logger *log.Logger
NeedNet string
Root string
PlatformConfig platform.Config
Fetcher *resource.Fetcher
State *state.State
}

// Run executes the stage of the given name. It returns true if the stage
Expand Down Expand Up @@ -286,6 +287,10 @@ func (e *Engine) acquireProviderConfig() (cfg types.Config, err error) {
// is unavailable. This will also render the config (see renderConfig) before
// returning.
func (e *Engine) fetchProviderConfig() (types.Config, error) {
if e.GenerateCloudConfig != "" {
return e.fetchGeneratedConfig()
}

platformConfigs := []platform.Config{
cmdline.Config,
system.Config,
Expand Down Expand Up @@ -331,6 +336,31 @@ func (e *Engine) fetchProviderConfig() (types.Config, error) {
return configFetcher.RenderConfig(cfg)
}

func (e *Engine) fetchGeneratedConfig() (types.Config, error) {
if e.GenerateCloudConfig != e.PlatformConfig.Name() {
return types.Config{}, fmt.Errorf("cannot generate %q config on %q platform", e.GenerateCloudConfig, e.PlatformConfig.Name())
}

cfg, err := e.PlatformConfig.GenerateConfig(e.Fetcher)
if err != nil {
return types.Config{}, err
}

e.State.FetchedConfigs = append(e.State.FetchedConfigs, state.FetchedConfig{
Kind: "user",
Source: fmt.Sprintf("%s-generator", e.GenerateCloudConfig),
Referenced: false,
})

configFetcher := ConfigFetcher{
Logger: e.Logger,
Fetcher: e.Fetcher,
State: e.State,
}

return configFetcher.RenderConfig(cfg)
}

func (e *Engine) signalNeedNet() error {
if err := executil.MkdirForFile(e.NeedNet); err != nil {
return err
Expand Down
37 changes: 20 additions & 17 deletions internal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,22 @@ func main() {

func ignitionMain() {
flags := struct {
configCache string
fetchTimeout time.Duration
needNet string
platform platform.Name
root string
stage stages.Name
stateFile string
version bool
logToStdout bool
configCache string
fetchTimeout time.Duration
generateCloudConfig string
needNet string
platform platform.Name
root string
stage stages.Name
stateFile string
version bool
logToStdout bool
}{}

flag.StringVar(&flags.configCache, "config-cache", "/run/ignition.json", "where to cache the config")
flag.DurationVar(&flags.fetchTimeout, "fetch-timeout", exec.DefaultFetchTimeout, "initial duration for which to wait for config")
flag.StringVar(&flags.needNet, "neednet", "/run/ignition/neednet", "flag file to write from fetch-offline if networking is needed")
flag.StringVar(&flags.generateCloudConfig, "generate-cloud-config", "", "generate a platform-specific config instead of fetching (e.g. azure)")
flag.Var(&flags.platform, "platform", fmt.Sprintf("current platform. %v", platform.Names()))
flag.StringVar(&flags.root, "root", "/", "root of the filesystem")
flag.Var(&flags.stage, "stage", fmt.Sprintf("execution stage. %v", stages.Names()))
Expand Down Expand Up @@ -104,14 +106,15 @@ func ignitionMain() {
os.Exit(3)
}
engine := exec.Engine{
Root: flags.root,
FetchTimeout: flags.fetchTimeout,
Logger: &logger,
NeedNet: flags.needNet,
ConfigCache: flags.configCache,
PlatformConfig: platformConfig,
Fetcher: &fetcher,
State: &state,
Root: flags.root,
FetchTimeout: flags.fetchTimeout,
GenerateCloudConfig: flags.generateCloudConfig,
Logger: &logger,
NeedNet: flags.needNet,
ConfigCache: flags.configCache,
PlatformConfig: platformConfig,
Fetcher: &fetcher,
State: &state,
}

err = engine.Run(flags.stage.String())
Expand Down
9 changes: 9 additions & 0 deletions internal/platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type Provider struct {
Init func(f *resource.Fetcher) error
Status func(stageName string, f resource.Fetcher, e error) error
DelConfig func(f *resource.Fetcher) error
// Generates an azure-specific Ignition config.
Comment thread
peytonr18 marked this conversation as resolved.
GenerateCloudConfig func(f *resource.Fetcher) (types.Config, error)

// Fetch, and also save output files to be written during files stage.
// Avoid, unless you're certain you need it.
Expand Down Expand Up @@ -104,6 +106,13 @@ func (c Config) DelConfig(f *resource.Fetcher) error {
}
}

func (c Config) GenerateConfig(f *resource.Fetcher) (types.Config, error) {
if c.p.GenerateCloudConfig != nil {
return c.p.GenerateCloudConfig(f)
}
return types.Config{}, ErrNoProvider
}

var configs = registry.Create("platform configs")

func Register(provider Provider) {
Expand Down
Loading