|
| 1 | +# Custom Configuration Design for azure-init |
| 2 | + |
| 3 | +## Objective |
| 4 | + |
| 5 | +The azure-init custom configuration architecture enables dynamic and flexible management of various settings for virtual machines provisioned with the light-weight agent. Customizable settings include SSH, IMDS, provisioning media, azure proxy agent, wireserver, and telemetry. |
| 6 | + |
| 7 | +## Design |
| 8 | + |
| 9 | +The system supports default configurations with user-specified overrides via configuration files or CLI parameters. |
| 10 | + |
| 11 | +### Key Features |
| 12 | + |
| 13 | +- **Config Validation**: Validates user-provided settings against supported options, rejecting invalid values during deserialization. |
| 14 | +- **Built-in Defaults**: The system defines defaults directly in the code, eliminating the need for a separate default config file. |
| 15 | +- **Merging of Configurations**: Combines configuration sources hierarchically, applying defaults first, followed by file-based overrides, and finally CLI parameters for the highest precedence. |
| 16 | + |
| 17 | +## Config File Structure |
| 18 | + |
| 19 | +**Format**: TOML |
| 20 | + |
| 21 | +- Users can override default settings by supplying a single configuration file or multiple `.toml` files in a directory. |
| 22 | + |
| 23 | +### CLI Parameters |
| 24 | + |
| 25 | +Example: `--config /etc/azure-init/` |
| 26 | + |
| 27 | +## Configuration Hierarchy for `azure-init` |
| 28 | + |
| 29 | +Configuration can be set via a single file, a directory containing multiple files, or the default values defined in the code. |
| 30 | + |
| 31 | +### Configuration Loading Order |
| 32 | + |
| 33 | +#### 1. Defaults in Code |
| 34 | + |
| 35 | +The configuration process starts with the built-in defaults specified in `Config::default()`. |
| 36 | + |
| 37 | +#### 2. Base File and Directory Loading Logic |
| 38 | + |
| 39 | +- After applying default values, `azure-init` checks for a base `azure-init.toml` file. If it exists, it is loaded as the base configuration. |
| 40 | +- If an `azure-init.toml.d` directory exists, its `.toml` files are loaded and merged in lexicographical order. |
| 41 | +- If neither the `azure-init.toml` nor the directory exists, the configuration remains as defined by the built-in defaults. |
| 42 | + |
| 43 | + ```text |
| 44 | + /etc/azure-init/ |
| 45 | + ├── azure-init.toml # Base configuration |
| 46 | + └── azure-init.toml.d/ |
| 47 | + ├── 01-network.toml # Additional network configuration |
| 48 | + ├── 02-ssh.toml # Additional SSH configuration |
| 49 | + └── 99-overrides.toml # Final overrides |
| 50 | + ``` |
| 51 | +
|
| 52 | +- Each `.toml` file is merged into the configuration in the sorted order. If two files define the same configuration field, the value from the file processed last will take precedence. For example, in the order above, the final value(s) would come from `99-overrides.toml`. |
| 53 | +
|
| 54 | +#### 3. CLI Override (`--config`) |
| 55 | +
|
| 56 | +- The `--config` flag specifies a configuration path that can point to either a single file or a directory. |
| 57 | + - **File:** If a file is specified, it is merged as the final layer, overriding all prior configurations. |
| 58 | + - **Directory:** If a directory is specified, `.toml` files within it are loaded and merged in, following the same rules specified in the Directory Loading Logic section. |
| 59 | + - **Example:** `azure-init --config /path/to/custom-config.toml` |
| 60 | +
|
| 61 | +### Example: Directory with Multiple .toml Files |
| 62 | +
|
| 63 | +**Command:** |
| 64 | +
|
| 65 | +```sh |
| 66 | +azure-init --config /path/to/custom-config-directory |
| 67 | +``` |
| 68 | + |
| 69 | +**Directory Structure:** |
| 70 | + |
| 71 | +```bash |
| 72 | +/path/to/custom-config-directory/ |
| 73 | +├── azure-init.toml # Base configuration |
| 74 | +└── azure-init.toml.d/ |
| 75 | + ├── 01-network.toml # Network configuration |
| 76 | + ├── 02-ssh.toml # SSH configuration |
| 77 | + └── 99-overrides.toml # Overrides |
| 78 | +``` |
| 79 | + |
| 80 | +**Order of Merging:** |
| 81 | + |
| 82 | +1. Applies defaults from `Config::default()` as defined in `config.rs`. |
| 83 | +2. Loads `azure-init.toml` as the base configuration, if present. |
| 84 | +3. Merges configuration `.toml` files found in `azure-init.toml.d` in lexicographical order. The last file in the sorted order takes precedence. |
| 85 | + - `01-network.toml` |
| 86 | + - `02-ssh.toml` |
| 87 | + - `99-overrides.toml` |
| 88 | +4. Applies any CLI overrides, either from a file or a directory. |
| 89 | + |
| 90 | +## Validation and Deserialization Process |
| 91 | + |
| 92 | +Azure Init uses strict validation on configuration fields to ensure they match expected types and values. If a configuration includes an unsupported value or incorrect type, deserialization will fail. |
| 93 | + |
| 94 | +### Error Handling During Deserialization |
| 95 | + |
| 96 | +- When a configuration file is loaded, its contents are parsed and converted from `.toml` into structured data. If a field in the file contains an invalid value (e.g., `query_sshd_config` is set to `"not_a_boolean"` instead of `true` or `false`), the parsing process will fail with a deserialization error due to the mismatched type. |
| 97 | + |
| 98 | +### Propagation of Deserialization Errors |
| 99 | + |
| 100 | +- When deserialization fails, an error is logged to indicate that the configuration file could not be parsed correctly. This error propagates through the application, causing the provisioning process to fail. The application will not proceed with provisioning if the configuration is invalid. |
| 101 | + |
| 102 | +### Example of an Unsupported Value |
| 103 | + |
| 104 | +Here’s an example configuration with an invalid value for `query_sshd_config`. This field expects a boolean (`true` or `false`), but in this case, an unsupported string value `"not_a_boolean"` is provided. |
| 105 | + |
| 106 | +```toml |
| 107 | +# Invalid value for query_sshd_config (not a boolean) |
| 108 | +[ssh] |
| 109 | +query_sshd_config = "not_a_boolean" # This will cause a validation failure |
| 110 | +``` |
| 111 | + |
| 112 | +## Sample of Valid Configuration File |
| 113 | + |
| 114 | +```toml |
| 115 | +[ssh] |
| 116 | +authorized_keys_path = ".ssh/authorized_keys" |
| 117 | +query_sshd_config = true |
| 118 | + |
| 119 | +[hostname_provisioners] |
| 120 | +backends = ["hostnamectl"] |
| 121 | + |
| 122 | +[user_provisioners] |
| 123 | +backends = ["useradd"] |
| 124 | + |
| 125 | +[password_provisioners] |
| 126 | +backends = ["passwd"] |
| 127 | + |
| 128 | +[imds] |
| 129 | +connection_timeout_secs = 2.0 |
| 130 | +read_timeout_secs = 60 |
| 131 | +total_retry_timeout_secs = 300 |
| 132 | + |
| 133 | +[provisioning_media] |
| 134 | +enable = true |
| 135 | + |
| 136 | +[azure_proxy_agent] |
| 137 | +enable = true |
| 138 | + |
| 139 | +[wireserver] |
| 140 | +connection_timeout_secs = 2.0 |
| 141 | +read_timeout_secs = 60 |
| 142 | +total_retry_timeout_secs = 1200 |
| 143 | + |
| 144 | +[telemetry] |
| 145 | +kvp_diagnostics = true |
| 146 | +``` |
| 147 | + |
| 148 | +## Behavior of `azure-init` on Invalid Configuration |
| 149 | + |
| 150 | +`azure-init` handles configuration issues by logging errors and either using default values or halting functionality, depending on the severity of the issue. Here’s how it responds to different types of problems: |
| 151 | + |
| 152 | +### 1. Invalid Configuration |
| 153 | + |
| 154 | +- If a configuration file contains syntax errors (e.g., malformed TOML) or unsupported values for fields (e.g., invalid enums), `azure-init` logs the error and terminates. The provisioning process does not proceed when configuration parsing fails. |
| 155 | + |
| 156 | +### 2. Missing or Invalid SSH Configuration |
| 157 | + |
| 158 | +- `query_sshd_config = true`: |
| 159 | + - `azure-init` attempts to dynamically query the authorized keys path using the `sshd -G` command. |
| 160 | + - If `sshd -G` succeeds: The dynamically queried path is used for the authorized keys. |
| 161 | + - If `sshd -G` fails: The failure is logged, but azure-init continues using the fallback path specified in authorized_keys_path (default: `.ssh/authorized_keys`). |
| 162 | +- `query_sshd_config = false`: |
| 163 | + - `azure-init` skips querying `sshd -G` entirely |
| 164 | + - The value in `authorized_keys_path` is used directly, without any dynamic path detection. |
| 165 | + |
| 166 | +### 3. Handling of Provisioners in `azure-init` |
| 167 | + |
| 168 | +The `azure-init` configuration allows for custom settings of hostnames, user creation, and password setup through the use of provisioners. If `backends` are specified but do not contain a valid provisioner, `azure-init` logs an error and halts provisioning. |
| 169 | + |
| 170 | +## Package Considerations |
| 171 | + |
| 172 | +To ensure smooth operation and compatibility across distributions, `azure-init`, should be packaged with a consistent configuration setup. |
| 173 | + |
| 174 | +- Distributions packaging `azure-init` are expected to maintain the base configuration file at `/etc/azure-init/azure-init.toml`, with necessary overrides applied from a `.d` subdirectory. |
0 commit comments