Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add serve_plain_dns to TLS config #102

Merged
merged 6 commits into from
May 9, 2024
Merged
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
4 changes: 2 additions & 2 deletions adguard/client_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type clientCommonModel struct {
ID types.String `tfsdk:"id"`
LastUpdated types.String `tfsdk:"last_updated"`
Name types.String `tfsdk:"name"`
Ids types.List `tfsdk:"ids"`
Ids types.Set `tfsdk:"ids"` // technically upstream accepts a list with duplicate values, but it doesn't make sense
UseGlobalSettings types.Bool `tfsdk:"use_global_settings"`
FilteringEnabled types.Bool `tfsdk:"filtering_enabled"`
ParentalEnabled types.Bool `tfsdk:"parental_enabled"`
Expand Down Expand Up @@ -81,7 +81,7 @@ func (o *clientCommonModel) Read(ctx context.Context, adg adguard.ADG, currState

// map response body to model
o.Name = types.StringValue(client.Name)
o.Ids, d = types.ListValueFrom(ctx, types.StringType, client.Ids)
o.Ids, d = types.SetValueFrom(ctx, types.StringType, client.Ids)
diags.Append(d...)
if diags.HasError() {
return
Expand Down
4 changes: 2 additions & 2 deletions adguard/client_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ func (d *clientDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
Description: "Name of the client",
Required: true,
},
"ids": schema.ListAttribute{
Description: "List of identifiers for this client (IP, CIDR, MAC, or ClientID)",
"ids": schema.SetAttribute{
Description: "Set of identifiers for this client (IP, CIDR, MAC, or ClientID)",
ElementType: types.StringType,
Computed: true,
},
Expand Down
8 changes: 4 additions & 4 deletions adguard/client_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ func (r *clientResource) Schema(_ context.Context, _ resource.SchemaRequest, res
stringplanmodifier.RequiresReplace(),
},
},
"ids": schema.ListAttribute{
Description: "List of identifiers for this client (IP, CIDR, MAC, or ClientID)",
"ids": schema.SetAttribute{
Description: "Set of identifiers for this client (IP, CIDR, MAC, or ClientID)",
ElementType: types.StringType,
Required: true,
Validators: []validator.List{
listvalidator.ValueStringsAre(
Validators: []validator.Set{
setvalidator.ValueStringsAre(
stringvalidator.RegexMatches(
regexp.MustCompile(`^[a-z0-9/.:-]+$`),
"must be an IP address/CIDR, MAC address, or only contain numbers, lowercase letters, and hyphens",
Expand Down
4 changes: 2 additions & 2 deletions adguard/client_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ resource "adguard_client" "test" {
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("adguard_client.test", "ids.#", "3"),
resource.TestCheckResourceAttr("adguard_client.test", "ids.2", "another-test-client"),
resource.TestCheckResourceAttr("adguard_client.test", "ids.1", "another-test-client"),
resource.TestCheckResourceAttr("adguard_client.test", "safesearch.enabled", "true"),
resource.TestCheckResourceAttr("adguard_client.test", "safesearch.services.#", "1"),
resource.TestCheckResourceAttr("adguard_client.test", "safesearch.services.0", "bing"),
Expand All @@ -98,7 +98,7 @@ resource "adguard_client" "test" {
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("adguard_client.test", "name", "Test Client Name Updated"),
resource.TestCheckResourceAttr("adguard_client.test", "ids.#", "3"),
resource.TestCheckResourceAttr("adguard_client.test", "ids.2", "another-test-client"),
resource.TestCheckResourceAttr("adguard_client.test", "ids.1", "another-test-client"),
),
},
// Delete testing automatically occurs in TestCase
Expand Down
5 changes: 5 additions & 0 deletions adguard/config_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ type tlsConfigModel struct {
KeyType types.String `tfsdk:"key_type"`
WarningValidation types.String `tfsdk:"warning_validation"`
ValidPair types.Bool `tfsdk:"valid_pair"`
ServePlainDns types.Bool `tfsdk:"serve_plain_dns"`
}

// attrTypes - return attribute types for this model
Expand All @@ -401,6 +402,7 @@ func (o tlsConfigModel) attrTypes() map[string]attr.Type {
"key_type": types.StringType,
"warning_validation": types.StringType,
"valid_pair": types.BoolType,
"serve_plain_dns": types.BoolType,
}
}

Expand All @@ -427,6 +429,7 @@ func (o tlsConfigModel) defaultObject() map[string]attr.Value {
"not_after": types.StringValue(""),
"dns_names": types.ListValueMust(types.StringType, []attr.Value{}),
"warning_validation": types.StringValue(""),
"serve_plain_dns": types.BoolValue(CONFIG_TLS_SERVE_PLAIN_DNS),
}
}

Expand Down Expand Up @@ -1040,6 +1043,7 @@ func (o *configCommonModel) Read(ctx context.Context, adg adguard.ADG, currState
stateTlsConfig.KeyType = types.StringValue(tlsConfig.KeyType)
stateTlsConfig.WarningValidation = types.StringValue(tlsConfig.WarningValidation)
stateTlsConfig.ValidPair = types.BoolValue(tlsConfig.ValidPair)
stateTlsConfig.ServePlainDns = types.BoolValue(tlsConfig.ServePlainDns)

// add to config model
o.Tls, d = types.ObjectValueFrom(ctx, tlsConfigModel{}.attrTypes(), &stateTlsConfig)
Expand Down Expand Up @@ -1529,6 +1533,7 @@ func (r *configResource) CreateOrUpdate(ctx context.Context, plan *configCommonM
tlsConfig.PortHttps = uint16(planTlsConfig.PortHttps.ValueInt64())
tlsConfig.PortDnsOverTls = uint16(planTlsConfig.PortDnsOverTls.ValueInt64())
tlsConfig.PortDnsOverQuic = uint16(planTlsConfig.PortDnsOverQuic.ValueInt64())
tlsConfig.ServePlainDns = planTlsConfig.ServePlainDns.ValueBool()

// regex to match a file path
var filePathIdentifier = regexp.MustCompile(`^/\w|\w:`)
Expand Down
4 changes: 4 additions & 0 deletions adguard/config_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ func (d *configDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
Description: "The validation warning message with the issue description",
Computed: true,
},
"serve_plain_dns": schema.BoolAttribute{
Description: "When `true`, plain DNS is allowed for incoming requests",
Computed: true,
},
},
},
},
Expand Down
3 changes: 2 additions & 1 deletion adguard/config_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestAccConfigDataSource(t *testing.T) {
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.cache_ttl_max", "0"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.cache_optimistic", "false"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.upstream_mode", "load_balance"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.use_private_ptr_resolvers", "true"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.use_private_ptr_resolvers", "false"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.resolve_clients", "true"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.local_ptr_upstreams.#", "0"),
resource.TestCheckResourceAttr("data.adguard_config.test", "dns.allowed_clients.#", "0"),
Expand All @@ -85,6 +85,7 @@ func TestAccConfigDataSource(t *testing.T) {
resource.TestCheckResourceAttr("data.adguard_config.test", "tls.port_https", "443"),
resource.TestCheckResourceAttr("data.adguard_config.test", "tls.port_dns_over_tls", "853"),
resource.TestCheckResourceAttr("data.adguard_config.test", "tls.certificate_chain", "/opt/adguardhome/ssl/server.crt"),
resource.TestCheckResourceAttr("data.adguard_config.test", "tls.serve_plain_dns", "true"),
// Verify internal attributes
resource.TestCheckResourceAttr("data.adguard_config.test", "id", "placeholder"),
resource.TestCheckResourceAttrSet("data.adguard_config.test", "last_updated"),
Expand Down
3 changes: 2 additions & 1 deletion adguard/config_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const CONFIG_DNS_CACHE_TTL_MIN = 0
const CONFIG_DNS_CACHE_TTL_MAX = 0
const CONFIG_DNS_CACHE_OPTIMISTIC = false
const CONFIG_DNS_UPSTREAM_MODE = "load_balance"
const CONFIG_DNS_USE_PRIVATE_PTR_RESOLVERS = true
const CONFIG_DNS_USE_PRIVATE_PTR_RESOLVERS = false
const CONFIG_DNS_RESOLVE_CLIENTS = true
const CONFIG_DHCP_ENABLED = false
const CONFIG_DHCP_V4_LEASE_DURATION = 0 // seconds
Expand All @@ -35,6 +35,7 @@ const CONFIG_TLS_FORCE_HTTPS = false
const CONFIG_TLS_PORT_HTTPS = 443
const CONFIG_TLS_PORT_DNS_OVER_TLS = 853
const CONFIG_TLS_PORT_DNS_OVER_QUIC = 853
const CONFIG_TLS_SERVE_PLAIN_DNS = true

var CONFIG_DNS_BOOTSTRAP = []string{"9.9.9.10", "149.112.112.10", "2620:fe::10", "2620:fe::fe:10"}
var CONFIG_DNS_UPSTREAM = []string{"https://dns10.quad9.net/dns-query"}
Expand Down
12 changes: 12 additions & 0 deletions adguard/config_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ func (r *configResource) Schema(_ context.Context, _ resource.SchemaRequest, res
Computed: true,
Optional: true,
Default: booldefault.StaticBool(CONFIG_DNS_USE_PRIVATE_PTR_RESOLVERS),
Validators: []validator.Bool{
checkLocalPtrUpstreams(),
},
},
"resolve_clients": schema.BoolAttribute{
Description: fmt.Sprintf("Whether reverse DNS resolution of clients' IP addresses is enabled. Defaults to `%t`", CONFIG_DNS_RESOLVE_CLIENTS),
Expand Down Expand Up @@ -727,6 +730,15 @@ func (r *configResource) Schema(_ context.Context, _ resource.SchemaRequest, res
Description: "The validation warning message with the issue description",
Computed: true,
},
"serve_plain_dns": schema.BoolAttribute{
Description: fmt.Sprintf("When `true`, plain DNS is allowed for incoming requests. Defaults to `%t`", CONFIG_TLS_SERVE_PLAIN_DNS),
Computed: true,
Optional: true,
Default: booldefault.StaticBool(CONFIG_TLS_SERVE_PLAIN_DNS),
Validators: []validator.Bool{
checkDnsEncryption(),
},
},
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions adguard/config_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ resource "adguard_config" "test" {
blocking_mode = "custom_ip"
blocking_ipv4 = "1.2.3.4"
blocking_ipv6 = "fe80::"
use_private_ptr_resolvers = true
local_ptr_upstreams = ["192.168.0.1", "192.168.0.2"]
allowed_clients = ["allowed-client", "192.168.200.200"]
}
Expand Down Expand Up @@ -83,6 +84,7 @@ resource "adguard_config" "test" {
}
tls = {
enabled = true
serve_plain_dns = false
server_name = "Test AdGuard Home"
certificate_chain = "/opt/adguardhome/ssl/server.crt"
private_key = "/opt/adguardhome/ssl/server.key"
Expand Down Expand Up @@ -133,6 +135,7 @@ resource "adguard_config" "test" {
resource.TestCheckResourceAttr("adguard_config.test", "dns.cache_ttl_min", "600"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.cache_ttl_max", "86400"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.cache_optimistic", "true"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.use_private_ptr_resolvers", "true"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.local_ptr_upstreams.#", "2"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.allowed_clients.#", "2"),
resource.TestCheckResourceAttr("adguard_config.test", "dns.allowed_clients.1", "allowed-client"),
Expand All @@ -146,6 +149,7 @@ resource "adguard_config" "test" {
resource.TestCheckResourceAttr("adguard_config.test", "tls.enabled", "true"),
resource.TestCheckResourceAttr("adguard_config.test", "tls.server_name", "Test AdGuard Home"),
resource.TestCheckResourceAttr("adguard_config.test", "tls.issuer", ""),
resource.TestCheckResourceAttr("adguard_config.test", "tls.serve_plain_dns", "false"),
// Verify dynamic values have any value set in the state.
resource.TestCheckResourceAttrSet("adguard_config.test", "id"),
resource.TestCheckResourceAttrSet("adguard_config.test", "last_updated"),
Expand Down Expand Up @@ -295,6 +299,7 @@ resource "adguard_config" "test" {
resource.TestCheckResourceAttr("adguard_config.test", "dhcp.static_leases.3.hostname", "test-lease-4"),
resource.TestCheckResourceAttr("adguard_config.test", "tls.enabled", "true"),
resource.TestCheckResourceAttr("adguard_config.test", "tls.server_name", "Test AdGuard Home Modified"),
resource.TestCheckResourceAttr("adguard_config.test", "tls.serve_plain_dns", "true"),
),
},
// Delete testing automatically occurs in TestCase
Expand Down
File renamed without changes.
52 changes: 52 additions & 0 deletions adguard/validator_dns_encryption.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package adguard

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

// validator confirms the DNS Config local PTR upstreams are set when the private PTR resolvers are enabled
var _ validator.Bool = checkDnsEncryptionValidator{}

type checkDnsEncryptionValidator struct {
}

func (v checkDnsEncryptionValidator) Description(_ context.Context) string {
return "\"tls.serve_plain_dns\" must be `true` when \"tls.enabled\" is set to `false`"
}

func (v checkDnsEncryptionValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

func (v checkDnsEncryptionValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
if req.ConfigValue.ValueBool() || req.ConfigValue.IsNull() {
// if set to true or null, config is valid
return
}

tlsEnabledPath := req.Path.ParentPath().AtName("enabled")

var tlsEnabled types.Bool

diags := req.Config.GetAttribute(ctx, tlsEnabledPath, &tlsEnabled)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

if !tlsEnabled.ValueBool() {
resp.Diagnostics.AddAttributeError(
tlsEnabledPath,
"DNS Encryption Config Invalid",
v.Description(ctx),
)
}
}

func checkDnsEncryption() validator.Bool {
return checkDnsEncryptionValidator{}
}
52 changes: 52 additions & 0 deletions adguard/validator_local_ptr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package adguard

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

// validator confirms the DNS Config local PTR upstreams are set when the private PTR resolvers are enabled
var _ validator.Bool = checkLocalPtrUpstreamsValidator{}

type checkLocalPtrUpstreamsValidator struct {
}

func (v checkLocalPtrUpstreamsValidator) Description(_ context.Context) string {
return "\"dns.local_ptr_upstreams\" must contain values when \"dns.use_private_ptr_resolvers\" is set to `true`"
}

func (v checkLocalPtrUpstreamsValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

func (v checkLocalPtrUpstreamsValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
if !req.ConfigValue.ValueBool() || req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
// if set to false or not set, config is valid
return
}

ptrUpstreamsPath := req.Path.ParentPath().AtName("local_ptr_upstreams")

var ptrUpstreams types.Set

diags := req.Config.GetAttribute(ctx, ptrUpstreamsPath, &ptrUpstreams)
resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

if ptrUpstreams.IsNull() || ptrUpstreams.IsUnknown() {
resp.Diagnostics.AddAttributeError(
ptrUpstreamsPath,
"DNS Config Use Private PTR Resolvers Invalid",
v.Description(ctx),
)
}
}

func checkLocalPtrUpstreams() validator.Bool {
return checkLocalPtrUpstreamsValidator{}
}
2 changes: 1 addition & 1 deletion docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: "3"
services:
adguardhome:
image: adguard/adguardhome
image: adguard/adguardhome:v0.107.48
container_name: adguardhome
restart: unless-stopped
volumes:
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ data "adguard_client" "test" {
- `blocked_services_pause_schedule` (Attributes) Sets periods of inactivity for filtering blocked services. The schedule contains 7 days (Sunday to Saturday) and a time zone. (see [below for nested schema](#nestedatt--blocked_services_pause_schedule))
- `filtering_enabled` (Boolean) Whether to have filtering enabled on this client
- `id` (String) Placeholder identifier attribute
- `ids` (List of String) List of identifiers for this client (IP, CIDR, MAC, or ClientID)
- `ids` (Set of String) Set of identifiers for this client (IP, CIDR, MAC, or ClientID)
- `ignore_querylog` (Boolean) Whether to this client writes to the query log
- `ignore_statistics` (Boolean) Whether to this client is included in the statistics
- `last_updated` (String) Timestamp of the last Terraform refresh
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ Read-Only:
- `port_https` (Number) The HTTPS port
- `private_key` (String) The private key, either the path to a file or a base64 encoded string of the private key in PEM format
- `private_key_saved` (Boolean) Whether the user has previously saved a private key
- `serve_plain_dns` (Boolean) When `true`, plain DNS is allowed for incoming requests
- `server_name` (String) The hostname of the TLS/HTTPS server
- `subject` (String) The subject of the first certificate in the chain
- `valid_cert` (Boolean) Whether the specified certificates chain is a valid chain of X.509 certificates
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ resource "adguard_client" "test" {

### Required

- `ids` (List of String) List of identifiers for this client (IP, CIDR, MAC, or ClientID)
- `ids` (Set of String) Set of identifiers for this client (IP, CIDR, MAC, or ClientID)
- `name` (String) Name of the client

### Optional
Expand Down
3 changes: 2 additions & 1 deletion docs/resources/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ Optional:
- `resolve_clients` (Boolean) Whether reverse DNS resolution of clients' IP addresses is enabled. Defaults to `true`
- `upstream_dns` (List of String) Upstream DNS servers. Defaults to the ones supplied by the default AdGuard Home configuration
- `upstream_mode` (String) Upstream DNS resolvers usage strategy. Valid values are `load_balance` (default), `parallel` and `fastest_addr`
- `use_private_ptr_resolvers` (Boolean) Whether to use private reverse DNS resolvers. Defaults to `true`
- `use_private_ptr_resolvers` (Boolean) Whether to use private reverse DNS resolvers. Defaults to `false`


<a id="nestedatt--filtering"></a>
Expand Down Expand Up @@ -332,6 +332,7 @@ Optional:
- `port_dns_over_quic` (Number) The DNS-over-Quic (DoQ) port. Set to `0` to disable. Defaults to `853`
- `port_dns_over_tls` (Number) The DNS-over-TLS (DoT) port. Set to `0` to disable. Defaults to `853`
- `port_https` (Number) The HTTPS port. Set to `0` to disable. Defaults to `443`
- `serve_plain_dns` (Boolean) When `true`, plain DNS is allowed for incoming requests. Defaults to `true`

Read-Only:

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ go 1.21
// replace github.com/gmichels/adguard-client-go => /path/to/adguard-client-go

require (
github.com/gmichels/adguard-client-go v0.7.0
github.com/gmichels/adguard-client-go v0.9.0
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-framework v1.4.2
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/gmichels/adguard-client-go v0.7.0 h1:y1qjO68CzcrDa4UAo5dxNBPO2K1HZtHSFlckQNRsqfU=
github.com/gmichels/adguard-client-go v0.7.0/go.mod h1:e/aasBtY19OZ/gnxt0J4xvbbRtJUyk03Jfi7R6ayBz4=
github.com/gmichels/adguard-client-go v0.9.0 h1:pUlOgbrboydMA1Rvd7JckTfyY8NH3ATRi0OCcO386As=
github.com/gmichels/adguard-client-go v0.9.0/go.mod h1:e/aasBtY19OZ/gnxt0J4xvbbRtJUyk03Jfi7R6ayBz4=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
Expand Down
Loading