feat(configgen): yaml.v3 typed-struct config marshal (closes #126)#130
Merged
Conversation
…p#126) Replaces internal/configgen/generator.go's text/template-based agent config generator with typed-struct marshalling through gopkg.in/yaml.v3. Defense-in-depth follow-up to GHSA-7hp6-g3pq-3pc3 — closes the entire YAML-injection class at the output side regardless of upstream validators. The public GeneratorInput / FirewallRule / LighthouseInfo / AdvancedUnsafeRoute types are unchanged; only the implementation moves from string-interpolation to yaml.v3 Encoder. - internal/configgen/marshal.go (new): typed nebulaConfig struct mirroring the previous template's shape. Inline PEM blocks use a literalString MarshalYAML for the `|` literal-block scalar form. - internal/configgen/generator.go: configTemplate, indentLines, and the template-based Generate are removed. Only public input types remain. - internal/configgen/generator_test.go: three multi-address tests converted from byte-equality assertions on flow-style + quoted IPs to parse-then-compare via yaml.Unmarshal, per your issue body. Added TestGenerate_LighthouseAndRelay (lighthouse+relay combo) and an assertion in TestGenerate_Lighthouse that `static_host_map: {}` is emitted explicitly (locks down the empty contract against future omitempty drift). - internal/configgen/advanced_test.go: TestGenerate_TunDevice_StructuralBreakCharsAreQuoted (new) is the defense-in-depth acceptance criterion: a TunDevice value containing \r, \n, ENQ (0x05), ", :, #, or trailing whitespace round-trips through yaml.Unmarshal exactly, and no extra top-level keys appear in the output (which would indicate YAML injection). Mobile bundle path (internal/mobilebundle/builder.go) uses the same GeneratorInput — no API change needed there. make ci green: vet, build, race tests, golangci-lint v2.12.0 ("0 issues."). All existing configgen tests pass plus the new LighthouseAndRelay test plus the 7-case defense-in-depth subtest.
a9264b1 to
47670a3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #126. Replaces
internal/configgen/generator.go'stext/template-based agent config generator with typed-struct marshalling throughgopkg.in/yaml.v3. Defense-in-depth follow-up to GHSA-7hp6 — closes the entire YAML-injection class at the output side regardless of what upstream validators allow.Public API (
GeneratorInput,FirewallRule,LighthouseInfo,AdvancedUnsafeRoute) unchanged; only the implementation moves.Changes
internal/configgen/marshal.go(new): typednebulaConfigstruct mirroring the previous template's shape. Inline PEM blocks use aliteralStringMarshalYAMLto produce the|literal-block scalar form.internal/configgen/generator.go:configTemplate,indentLines, and the template-basedGenerateare removed. Only public input types remain.internal/configgen/generator_test.go:StaticHostMap_PerAddress,LighthouseHosts_AllAddresses,MultipleLighthousesEachMulti) converted from byte-equality on flow-style + quoted IPs to parse-then-compare viayaml.Unmarshal, per the suggestion in your issue body.TestGenerate_LighthouseAndRelaycovering the lighthouse+relay combo (botham_lighthouse: trueandam_relay: true).TestGenerate_Lighthousenow also asserts thatstatic_host_map: {}is emitted explicitly — locks down the empty contract against a futureomitemptyrefactor silently dropping the key.internal/configgen/advanced_test.go:TestGenerate_TunDevice_StructuralBreakCharsAreQuoted(new) is the defense-in-depth acceptance criterion. ATunDevicevalue containing\r,\n, ENQ (0x05),\",:,#, or trailing whitespace round-trips throughyaml.Unmarshalexactly, with no extra top-level keys appearing in the output (which would indicate YAML injection). Seven sub-cases, all pass.Mobile bundle path (
internal/mobilebundle/builder.go) uses the sameGeneratorInput— no API change needed there.Acceptance vs your issue body
Pre-flight
`make ci` green: vet, build, race tests, golangci-lint v2.12.0 (`0 issues.`). All existing configgen tests pass + the new `LighthouseAndRelay` test + the 7-case defense-in-depth subtest.