Skip to content

Instantly share code, notes, and snippets.

@andrewkroh
Last active November 9, 2024 01:44
Show Gist options
  • Save andrewkroh/e7212a1ff033a0227f7c8d3fa7df8973 to your computer and use it in GitHub Desktop.
Save andrewkroh/e7212a1ff033a0227f7c8d3fa7df8973 to your computer and use it in GitHub Desktop.
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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.
// This tool helps refactor the file
// https://github.com/elastic/go-libaudit/blob/v2.5.0/aucoalesce/normalizations.yaml
// for https://github.com/elastic/go-libaudit/issues/169.
package main
import (
"fmt"
"log"
"os"
"regexp"
"github.com/goccy/go-yaml/ast"
"github.com/goccy/go-yaml/parser"
)
// flattenObjects processes a YAML AST SequenceNode to flatten `subject` and `object` maps.
func flattenObjects(normalizations *ast.SequenceNode) {
for _, item := range normalizations.Values {
// The entries in macros all begin with anchor nodes.
if anchor, ok := item.(*ast.AnchorNode); ok {
item = anchor.Value
}
if mapping, ok := item.(*ast.MappingNode); ok {
var newValues []*ast.MappingValueNode
for _, mappingValue := range mapping.Values {
keyName := mappingValue.Key.String()
switch keyName {
case "subject", "object":
prefix := keyName + "_"
if subValue, ok := mappingValue.Value.(*ast.MappingValueNode); ok {
newValues = append(newValues, &ast.MappingValueNode{
Key: mapKey(prefix, subValue.Key),
BaseNode: subValue.BaseNode,
Start: subValue.Start,
Value: subValue.Value,
FootComment: subValue.FootComment,
})
} else if subNode, ok := mappingValue.Value.(*ast.MappingNode); ok {
for _, subValue := range subNode.Values {
newValues = append(newValues, &ast.MappingValueNode{
Key: mapKey(prefix, subValue.Key),
BaseNode: subValue.BaseNode,
Start: subValue.Start,
Value: subValue.Value,
FootComment: subValue.FootComment,
})
}
}
default:
// Retain all other mappings
newValues = append(newValues, mappingValue)
}
}
// Update mapping.Values with flattened newValues
mapping.Values = newValues
}
}
}
func mapKey(prefix string, n ast.MapKeyNode) *ast.StringNode {
token := n.GetToken()
token.Position.Column -= 2
return &ast.StringNode{
BaseNode: &ast.BaseNode{},
Token: token,
Value: prefix + n.String(),
}
}
func main() {
data, err := os.ReadFile("normalizations.yaml")
if err != nil {
log.Fatal(err)
}
// Fix this section.
// https://github.com/elastic/go-libaudit/blob/5216c7618d6847f386ff0d8d8b8c3d9ffe875916/aucoalesce/normalizations.yaml#L1262-L1263
re := regexp.MustCompile(`(?m):\n\s+\[`)
data = re.ReplaceAll(data, []byte(": ["))
root, err := parser.ParseBytes(data, parser.ParseComments)
if err != nil {
log.Fatal(err)
}
rootMappingNode := root.Docs[0].Body.(*ast.MappingNode)
for _, mappingValue := range rootMappingNode.Values {
// All root entries in the file are sequences.
seqNode, ok := mappingValue.Value.(*ast.SequenceNode)
if !ok {
log.Fatalf("Expected sequence node, but got %T for %s", mappingValue.Value, mappingValue.Key.String())
}
flattenObjects(seqNode)
}
fmt.Println(root.String())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment