Skip to content

Releases: ClessLi/bifrost

v1.1.0-alpha.3

15 Jan 06:14

Choose a tag to compare

[v1.1.0-alpha.3] - 2025-01-10

Bug Fixes

  • fix known vulnerabilities, CVE IDs as follows: CVE-2024-51744, CVE-2023-45288, CVE-2024-45338
  • resolv: adjust the include context loading logic to ensure that the config graph has a unique topology based on the main config as the starting vertex, and stores configs associated with disabled (or unavailable) include contexts.
  • resolv: adjust the include context to load logic from the file system and avoid cycle loading; adjust the main context serialization logic.

Features

  • resolv: nginx configuration Context adds methods for Enable/Disable conversion
  • resolv: change the Include context from statically including sub configs to dynamically including each sub configs the graph data structure of the Main context.

BREAKING CHANGE

changed Nginx configuration Context interface object related methods and its JSON format serialization structure.

The methods for the Context has been changed as follows:

Methods of addition:

type Context interface {
    ...
    // Enable/Disable conversion methods
    IsEnabled() bool
    Enable() Context
    Disable() Context
}

The difference in the output of the ConfigLines method between enabled and disabled Context objects:

// Code:
exampleCtx := NewContext(context_type.TypeConfig, "conf.d/disabled_location.conf").Insert(
    NewContext(context_type.TypeComment, "disabled config"),
    0,
).Insert(
    NewContext(context_type.TypeLocation, "~ /test").Insert(
        NewContext(context_type.TypeDirective, "return 404"),
        0,
    ),
    1,
).Insert(
    NewContext(context_type.TypeLocation, "~ /has-disabled-ctx").Insert(
        NewContext(context_type.TypeComment, "disabled if ctx"),
        0,
    ).Insert(
        NewContext(context_type.TypeIf, "($is_enabled ~* false)").Disable().Insert(
            NewContext(context_type.TypeDirective, "set $is_enabled true").Disable(),
            0,
        ).Insert(
            NewContext(context_type.TypeDirective, "return 404"),
            1,
        ),
        1,
    ),
    2,
).Insert(
    NewContext(context_type.TypeComment, "}"),
    3,
).Insert(
    NewContext(context_type.TypeComment, "}"),
    4,
)
enabledLines, _ := exampleCtx.ConfigLines(false)
fmt.Println("Enabled Contents:\n" + strings.Join(enabledLines, "\n"))
fmt.Println("")
disabledLines, _ := exampleCtx.Disable().ConfigLines(false)
fmt.Println("Disabled Contents:\n" + strings.Join(disabledLines, "\n"))
// Output:
//  Enabled Contents:
//  # disabled config
//  location ~ /test {
//      return 404;
//  }
//  location ~ /has-disabled-ctx {
//      # disabled if ctx
//      # if ($is_enabled ~* false) {
//      #     # set $is_enabled true;
//      #     return 404;
//      # }
//  }
//  # }
//  # }
//
//  Disabled Contents:
//  # # disabled config
//  # location ~ /test {
//  #     return 404;
//  # }
//  # location ~ /has-disabled-ctx {
//  #     # disabled if ctx
//  #     # if ($is_enabled ~* false) {
//  #     #     # set $is_enabled true;
//  #     #     return 404;
//  #     # }
//  # }
//  # # }
//  # # }

The Context JSON format serialization structure changes as follows:

Before:

{
  "main-config":"C:\\test\\nginx.conf",
  "configs":{
    "C:\\test\\nginx.conf":{
      "context-type":"config",
      "value":"C:\\test\\nginx.conf",
      "params":[
        {
          "context-type":"http",
          "params":[
            {
              "context-type":"server",
              "params":[
                {
                  "context-type":"directive",
                  "value":"listen 80"
                },
                {
                  "context-type":"directive",
                  "value":"server_name example.com"
                },
                {
                  "context-type":"include",
                  "value":"conf.d/disabled_location.conf"
                },
                {
                  "context-type":"include",
                  "value":"conf.d/strange_location.conf"
                }
              ]
            },
            {
              "context-type":"comment",
              "value":"disabled server context"
            },
            {
              "context-type":"comment",
              "value":"server { # disabled server"
            },
            {
              "context-type":"comment",
              "value":" listen 8080;"
            },
            {
              "context-type":"comment",
              "value":" server_name example.com;"
            },
            {
              "context-type":"comment",
              "value":" # location ~ /disabled-location {"
            },
            {
              "context-type":"comment",
              "value":" # proxy_pass http://disabled-url;"
            },
            {
              "context-type":"comment",
              "value":" # }"
            },
            {
              "context-type":"comment",
              "value":" include conf.d/disabled_location.conf;"
            },
            {
              "context-type":"comment",
              "value":" include conf.d/strange_location.conf;"
            },
            {
              "context-type":"comment",
              "value":"}"
            }
          ]
        }
      ]
    },
    "conf.d/disabled_location.conf":{
      "context-type":"config",
      "value":"conf.d/disabled_location.conf",
      "params":[
        {
          "context-type":"comment",
          "value":"# disabled config"
        },
        {
          "context-type":"comment",
          "value":"location ~ /test {"
        },
        {
          "context-type":"comment",
          "value":"return 404;"
        },
        {
          "context-type":"comment",
          "value":"}"
        },
        {
          "context-type":"comment",
          "value":"location ~ /has-disabled-ctx {"
        },
        {
          "context-type":"comment",
          "value":"# disabled if ctx"
        },
        {
          "context-type":"comment",
          "value":"# if ($is_enabled ~* false) {"
        },
        {
          "context-type":"comment",
          "value":"# # set $is_enabled true;"
        },
        {
          "context-type":"comment",
          "value":"# return 404;"
        },
        {
          "context-type":"comment",
          "value":"# }"
        },
        {
          "context-type":"comment",
          "value":"}"
        },
        {
          "context-type":"comment",
          "value":"# }"
        },
        {
          "context-type":"comment",
          "value":"}"
        }
      ]
    },
    "conf.d/strange_location.conf":{
      "context-type":"config",
      "value":"conf.d/strange_location.conf",
      "params":[
        {
          "context-type":"comment",
          "value":"strange config"
        },
        {
          "context-type":"location",
          "value":"~ /normal-loc",
          "params":[
            {
              "context-type":"directive",
              "value":"return 200"
            }
          ]
        },
        {
          "context-type":"comment",
          "value":"location ~ /strange-loc {"
        },
        {
          "context-type":"comment",
          "value":" if ($strange ~* this_is_a_strange_if_ctx) {"
        },
        {
          "context-type":"comment",
          "value":" return 404;"
        },
        {
          "context-type":"comment",
          "value":" proxy_pass http://strange_url;"
        },
        {
          "context-type":"comment",
          "value":"}"
        }
      ]
    }
  }
}

After (unconverted):

{
    "main-config":"C:\\test\\nginx.conf",
    "configs":{
        "C:\\test\\nginx.conf":{
            "enabled":true,
            "context-type":"config",
            "value":"C:\\test\\nginx.conf",
            "params":[
                {
                    "enabled":true,
                    "context-type":"http",
                    "params":[
                        {
                            "enabled":true,
                            "context-type":"server",
                            "params":[
                                {
                                    "enabled":true,
                                    "context-type":"directive",
                                    "value":"listen 80"
                                },
                                {
                                    "enabled":true,
                                    "context-type":"directive",
                                    "value":"server_name example.com"
                                },
                                {
                                    "enabled":true,
                                    "context-type":"include",
                                    "value":"conf.d/disabled_location.conf"
                                },
                                {
                                    "enabled":true,
                                    "context-type":"include",
                                    "value":"conf.d/strange_location.conf"
                                }
                            ]
                        },
                        {
                            "context-type":"comment",
                            "value":"disabled server context"
                        },
                        {
                            "context-type":"comment",
                            "value":"server { # disabled server"
                        },
                        {
                ...
Read more

v1.0.12

24 Apr 01:37

Choose a tag to compare

v1.0.12 - 2024-04-24

Features

  • resolv: refactored the Context JSON format serialization structure to simplify serialization/deserialization operations, making the serialization structure more universal and unified.

BREAKING CHANGE

Changed the serialization structure of the Context JSON format, as well as the new functions for the Directive and Comment context objects.

The Context JSON format serialization structure changes as follows:

Before:

{
    "main-config": "C:\\test\\test.conf",
    "configs":
    {
        "C:\\test\\test.conf":
        [
            {
                "http":
                {
                    "params":
                    [
                        {
                            "inline": true, "comments": "test comment"
                        },
                        {
                            "server":
                            {
                                "params":
                                [
                                    {
                                        "directive": "server_name", "params": "testserver"
                                    },
                                    {
                                        "location": {"value": "~ /test"}
                                    },
                                    {
                                        "include":
                                        {
                                            "value": "conf.d\\include*conf",
                                            "params": ["conf.d\\include.location1.conf", "conf.d\\include.location2.conf"]
                                        }
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        ],
        "conf.d\\include.location1.conf":
        [
            {
                "location": {"value": "~ /test1"}
            }
        ],
        "conf.d\\include.location2.conf":
        [
            {
                "location": {"value": "^~ /test2"}
            }
        ]
    }
}

After:

{
    "main-config": "C:\\test\\test.conf",
    "configs":
    {
        "C:\\test\\test.conf":
        {
            "context-type": "config",
            "value": "C:\\test\\test.conf",
            "params":
            [
                {
                    "context-type": "http",
                    "params":
                    [
                        {
                            "context-type": "inline_comment", "value": "test comment"
                        },
                        {
                            "context-type": "server",
                            "params":
                            [
                                {
                                    "context-type": "directive", "value": "server_name testserver"
                                },
                                {
                                    "context-type": "location", "value": "~ /test"
                                },
                                {
                                    "context-type": "include",
                                    "value": "conf.d\\include*conf",
                                    "params": ["conf.d\\include.location1.conf", "conf.d\\include.location2.conf"]
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        "conf.d\\include.location1.conf":
        {
            "context-type": "config",
            "value": "conf.d\\include.location1.conf",
            "params":
            [
                {
                    "context-type": "location", "value": "~ /test1"
                }
            ]
        },
        "conf.d\\include.location2.conf":
        {
            "context-type": "config",
            "value": "conf.d\\include.location2.conf",
            "params":
            [
                {
                    "context-type": "location", "value": "^~ /test2"
                }
            ]
        }
    }
}

The code migration example for creating function calls for Directive and Comment context objects is as follows:

Before:

import (
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context/local"
)

// new directive context
newDirective := local.NewDirective("some_directive", "some params")
// new comment context
newComment := local.NewComment("some comments", false)
newComment := local.NewComment("some inline comments", true)

After:

import (
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context/local"
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context_type"
)

// new directive context
newDirective := local.NewContext(context_type.TypeDirective, "some_directive some params")
// new comment context
newComment := local.NewContext(context_type.TypeComment, "some comments")
newInlineComment := local.NewContext(context_type.TypeInlineComment, "some inline comments")

v1.0.11

01 Apr 09:54

Choose a tag to compare

v1.0.11 - 2024-04-01

Other Changes

  • fix to skip contaminated version numbers on pkg.go.dev.

BREAKING CHANGE

disable contaminated product package versions v1.0.9 and v1.0.10 on pkg.go.dev.

Code migration requires changing the version of the bifrost package from v1.0.9 or v1.0.10 to v1.0.11, as shown in the following example:

go.mod:

require (
	github.com/ClessLi/bifrost v1.0.11
)

v1.0.9

01 Apr 02:02

Choose a tag to compare

v1.0.9 - 2024-04-01

Bug Fixes

  • fix 1 Dependabot alert.
  • resolv: fix string containing matching logic in the KeyWords.Match() method.

Features

  • resolv: interface the Main Context.
  • resolv: preliminary completion of the development and testing of the resolve V3 version, as well as the update of the bifrost service to the resolve V3 version.
  • resolv: complete the writing of the KeyWords class and conduct preliminary unit testing of related methods for this class
  • resolv: preliminary completion of V3 local library unit testing and repair.
  • resolv: complete functional unit testing of V3 local.Include Context.
  • resolv: add V3 resolv lib.
  • resolv: add V3 resolv lib.

BREAKING CHANGE

replacing the nginx configuration resolving library from version V2 to V3.

To migrate the code follow the example below:

Before:

import (
	"github.com/ClessLi/bifrost/pkg/resolv/V2/nginx/configuration"
)

nginxConfFromPath, err := configuration.NewConfigurationFromPath(configAbsPath)
nginxConfFromJsonBytes, err := configuration.NewConfigurationFromJsonBytes(configJsonBytes)

After:

import (
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration"
)

nginxConfFromPath, err := configuration.NewNginxConfigFromFS(configAbsPath)
nginxConfFromJsonBytes, err := configuration.NewNginxConfigFromJsonBytes(configJsonBytes)

Example for querying and inserting context:

import (
	"fmt"

	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration"
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context"
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context/local"
)

conf, err := configuration.NewNginxConfigFromJsonBytes(jsondata)
if err != nil {
	t.Fatal(err)
}
for _, pos := range conf.Main().QueryByKeyWords(context.NewKeyWords(context_type.TypeHttp)).Target().
	QueryByKeyWords(context.NewKeyWords(context_type.TypeServer)).Target().
	QueryAllByKeyWords(context.NewKeyWords(context_type.TypeDirective).SetStringMatchingValue("server_name test1.com")) {  // query `server` context, its server name is "test1.com"
	server, _ := pos.Position()
	if server.QueryByKeyWords(context.NewKeyWords(context_type.TypeDirective).SetRegexpMatchingValue("^listen 80$")).Target().Error() != nil// query `server` context, its listen port is 80
		continue
	}
	// query the "proxy_pass" `directive` context, which is in `if` context(value: "($http_api_name != '')") and `location` context(value: "/test1-location")
	ctx, idx := server.QueryByKeyWords(context.NewKeyWords(context_type.TypeLocation).SetRegexpMatchingValue(`^/test1-location$`)).Target().
		QueryByKeyWords(context.NewKeyWords(context_type.TypeIf).SetRegexpMatchingValue(`^\(\$http_api_name != ''\)$`)).Target().
		QueryByKeyWords(context.NewKeyWords(context_type.TypeDirective).SetStringMatchingValue("proxy_pass")).Position()
	// insert an inline comment after the "proxy_pass" `directive` context
	err = ctx.Insert(local.NewComment(fmt.Sprintf("[%s]test comments", time.Now().String()), true), idx+1).Error()
	if err != nil {
		return err
	}
}

Examples for building nginx context object:

import (
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context/local"
	"github.com/ClessLi/bifrost/pkg/resolv/V3/nginx/configuration/context_type"
)

// new main context
newMainContext, err := local.NewMain("/usr/local/nginx/conf/nginx.conf")
// new directive context
newDirective := local.NewDirective("some_directive", "some params")
// new comment context
newComment := local.NewComment("some comments", false)
// new other context
newConfig := local.NewContext(context_type.TypeConfig, "conf.d/location.conf")
newInclude := local.NewContext(context_type.TypeInclude, "conf.d/*.conf")
newHttp := local.NewContext(context_type.TypeHttp, "")
...

v1.0.8

06 Jun 06:57

Choose a tag to compare

v1.0.8 - 2022-06-06

Bug Fixes

  • fix Go-Yaml vulnerability, CVE ID: CVE-2022-28948

v1.0.7

11 May 06:12

Choose a tag to compare

v1.0.7 - 2022-05-11

Bug Fixes

  • resolv: expose Location context
  • resolv: fix the bug that the Truncate method of dumper will modify the completed dump data

Features

  • resolv: KeyWords interface adds the feature of cascade retrieval

v1.0.6

15 Apr 07:40

Choose a tag to compare

v1.0.6 - 2022-04-15

Bug Fixes

  • resolv: fix the bug that the parseKeyword func of the querier parses the keyword value abnormally

v1.0.5

18 Feb 12:52

Choose a tag to compare

v1.0.5 - 2022-02-18

Bug Fixes

  • bifrost: fix the bug that the message sent by the gRPC server exceeds the limit size
  • resolv: fix the bug that cannot clean up the expired configuration file archive normally

Pull Requests

  • Merge pull request #11 from ClessLi/master

v1.0.4

13 Feb 08:01

Choose a tag to compare

v1.0.4 - 2022-02-13

Bug Fixes

  • bifrost_client: fix that when calling different Bifrost client connections, the obtained Bifrost service
    instances are the same
  • middleware: the response data is modified when the 'logging' middleware logs the response data
  • resolve: fix known bugs

Pull Requests

  • Merge pull request #14 from ClessLi/release/1.0.3
  • Merge pull request #13 from
    ClessLi/hotfix/middleware-logging-limit-result
  • Merge pull request #12 from
    ClessLi/hotfix/bifrost-client-singleton-ins
  • Merge pull request #10 from
    ClessLi/hotfix/bifrost-client-singleton-ins

v1.0.3

09 Feb 10:05
1753bd9

Choose a tag to compare

v1.0.3 - 2022-01-09

Bug Fixes

  • update jwt-go
  • web_server_log_watcher: repair the WatcherManager cannot converge quickly, after the WebServerLogWatcher.Watch
    client is disconnected
  • web_server_log_watcher: fix the bug that FileWatcher cannot be closed normally
  • web_server_status: no fatal to get platform information
  • bifrost_client: fix that when calling different Bifrost client connections, the obtained Bifrost service instances are the same
  • middleware: the response data is modified when the 'logging' middleware logs the response data

Code Refactoring

  • bifrost: the Bifrost grpc protocol changes
  • middleware: separate the 'begin' parameter and adjust it to a non required option

Features

  • preliminary completion of grpc server service layer logging middleware
  • bifrost: add web server statistics feature and add bifrost grpc client
  • client: fix grpc client support grpc streaming
  • web_server_config: reconstruct Bifrost grpc service structure
  • web_server_config: reformulate the transport layer, endpoint layer and service layer
  • web_server_log_watcher: add file watcher libs, web server log watcher grpc server and options/configs of this
    service
  • web_server_log_watcher: complete the WebServerLogWatcher service test for grpc server and client
  • web_server_status: add feature of web server status
  • web_server_status: complete the compilation of monitor library, config, options and store
  • web_server_status: complete the 'WebServerStatus' service store layer
  • web_server_status: complete the preparation of WebServerStatus grpc server and client

Pull Requests

  • Merge pull request #6 from ClessLi/feature/restructure

BREAKING CHANGE

the grpc protocol of Bifrost has been changed, and service authentication is not supported temporarily.

To migrate the code of the Bifrost gRPC client follow the example below:

Before:

data, err := bifrostClient.ViewConfig(...) // view web server config

data, err := bifrostClient.GetConfig(...) // get web server config

resp, err := bifrostClient.UpdateConfig(..., reqData, ...) // update web server config

data, err := bifrostClient.Status(...) // view web server state

data, err := bifrostClient.ViewStatistics(...) // view web server statistics

watcher, err := bifrostClient.WatchLog(...) // watching web server log

After:

// web server config

servernames, err := bifrostClient.WebServerConfig().GetServerNames() // get web server names

data, err := bifrostClient.WebServerConfig().Get(servername) // view web server config

err := bifrostClient.WebServerConfig().Update(servername, data) // update web server config

// web server status

metrics, err := bifrostClient.WebServerStatus().Get() // view web server status

// web server statistics

statistics, err := bifrostClient.WebServerStatistics().Get(servername) // view web server statistics

// web server log watcher

outputChan, cancel, err := bifrostClient.WebServerLogWatcher().Watch(request) // watch web server log