-
Notifications
You must be signed in to change notification settings - Fork 537
feat(otelcol): add support for htpasswd file authentication #3916
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
Changes from 2 commits
c48d7b5
2389d55
13210c8
daab23e
4c8b355
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -36,27 +36,73 @@ otelcol.auth.basic "<LABEL>" { | |||||||||||||||||
|
|
||||||||||||||||||
| ## Arguments | ||||||||||||||||||
|
|
||||||||||||||||||
| {{< admonition type="caution" >}} | ||||||||||||||||||
| The top-level `username` and `password` arguments are deprecated and should not be used for new configurations. Use | ||||||||||||||||||
| the `client_auth` block for client authentication and the `htpasswd` block for server authentication instead. | ||||||||||||||||||
| {{< /admonition >}} | ||||||||||||||||||
|
|
||||||||||||||||||
| You can use the following arguments with `otelcol.auth.basic`: | ||||||||||||||||||
|
|
||||||||||||||||||
| | Name | Type | Description | Default | Required | | ||||||||||||||||||
| | ---------- | -------- | -------------------------------------------------- | ------- | -------- | | ||||||||||||||||||
| | `password` | `secret` | Password to use for basic authentication requests. | | yes | | ||||||||||||||||||
| | `username` | `string` | Username to use for basic authentication requests. | | yes | | ||||||||||||||||||
| | Name | Type | Description | Default | Required | | ||||||||||||||||||
| |------------|----------|-----------------------------------------------------------------|---------|----------| | ||||||||||||||||||
| | `password` | `secret` | (Deprecated) Password to use for basic authentication requests. | | no | | ||||||||||||||||||
| | `username` | `string` | (Deprecated) Username to use for basic authentication requests. | | no | | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| ## Blocks | ||||||||||||||||||
|
|
||||||||||||||||||
| You can use the following block with `otelcol.auth.basic`: | ||||||||||||||||||
|
|
||||||||||||||||||
| | Block | Description | Required | | ||||||||||||||||||
| | -------------------------------- | -------------------------------------------------------------------------- | -------- | | ||||||||||||||||||
| |----------------------------------|----------------------------------------------------------------------------|----------| | ||||||||||||||||||
| | [`client_auth`][client_auth] | Configures client authentication credentials for exporters | no | | ||||||||||||||||||
| | [`debug_metrics`][debug_metrics] | Configures the metrics that this component generates to monitor its state. | no | | ||||||||||||||||||
| | [`htpasswd`][htpasswd] | Configures server authentication using htpasswd format for receivers | no | | ||||||||||||||||||
|
|
||||||||||||||||||
| [client_auth]: #client_auth | ||||||||||||||||||
| [debug_metrics]: #debug_metrics | ||||||||||||||||||
| [htpasswd]: #htpasswd | ||||||||||||||||||
|
|
||||||||||||||||||
| ### `client_auth` | ||||||||||||||||||
|
|
||||||||||||||||||
| The `client_auth` block configures credentials that client extensions (such as exporters) will use to authenticate to servers. | ||||||||||||||||||
|
||||||||||||||||||
| The `client_auth` block configures credentials that client extensions (such as exporters) will use to authenticate to servers. | |
| The `client_auth` block configures credentials that client extensions (such as exporters) use to authenticate to servers. |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| | Name | Type | Description | Default | Required | | |
| |------------|----------|-----------------------------------------------------|---------|----------| | |
| | `password` | `string` | Password to use for basic authentication requests | | yes | | |
| | `username` | `string` | Username to use for basic authentication requests | | yes | | |
| | Name | Type | Description | Default | Required | | |
| | ---------- | -------- | -------------------------------------------------- | ------- | -------- | | |
| | `password` | `string` | Password to use for basic authentication requests. | | yes | | |
| | `username` | `string` | Username to use for basic authentication requests. | | yes | |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| | Name | Type | Description | Default | Required | | |
| |----------|----------|--------------------------------------------------------------------|---------|----------| | |
| | `file` | `string` | Path to the htpasswd file to use for basic authentication requests | `""` | no | | |
| | `inline` | `string` | The htpasswd file content in inline format | `""` | no | | |
| | Name | Type | Description | Default | Required | | |
| | -------- | -------- | --------------------------------------------------------------------- | ------- | -------- | | |
| | `file` | `string` | Path to the `htpasswd` file to use for basic authentication requests. | `""` | no | | |
| | `inline` | `string` | The `htpasswd` file content in inline format. | `""` | no | |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| You can specify either `file`, `inline`, or both. When using `inline`, the format should be `username:password` with | |
| each user on a new line. | |
| You can specify either `file`, `inline`, or both. | |
| When you use `inline`, the format should be `username:password` with each user on a new line. |
clayton-cornell marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between this example and the Forward signals to exporters example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference is that the first (forward signals to exporters uses the deprecated username and password top-level arguments whereas this uses the new client authentication block. Since I have split this into client and server authentication examples, I think I should just move this a below Forward signals to exporters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think pairing them together would be better, but similar to the other thread I'm not a fan of showing deprecated fields in config examples in most cases. Let's see what our docs team says.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| To migrate from the deprecated `username` and `password` attributes, move them into the `client_auth` block for client | |
| authentication. | |
| {{< /admonition >}} | |
| To migrate from the deprecated `username` and `password` attributes, move them into the `client_auth` block for client authentication. | |
| {{< /admonition >}} | |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| This example configures [`otelcol.receiver.otlp`][otelcol.receiver.otlp] to use basic authentication using an htpasswd | |
| file containing the users to use for basic auth: | |
| This example configures [`otelcol.receiver.otlp`][otelcol.receiver.otlp] to use basic authentication using an `htpasswd` file containing the users to use for basic authentication: |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| This example shows how to specify htpasswd content directly in the configuration: | |
| This example shows how to specify `htpasswd` content directly in the configuration: |
clayton-cornell marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| package basic | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
|
|
||
| "github.com/grafana/alloy/internal/component" | ||
|
|
@@ -15,6 +16,11 @@ import ( | |
| "go.opentelemetry.io/collector/pipeline" | ||
| ) | ||
|
|
||
| var ( | ||
| errNoCredentialSource = errors.New("no credential source provided") | ||
| errNoPasswordProvided = errors.New("no password provided") | ||
| ) | ||
|
|
||
| func init() { | ||
| component.Register(component.Registration{ | ||
| Name: "otelcol.auth.basic", | ||
|
|
@@ -29,10 +35,41 @@ func init() { | |
| }) | ||
| } | ||
|
|
||
| type HtpasswdConfig struct { | ||
| File string `alloy:"file,attr,optional"` | ||
| Inline string `alloy:"inline,attr,optional"` | ||
| } | ||
|
|
||
| func (c HtpasswdConfig) convert() *basicauthextension.HtpasswdSettings { | ||
| return &basicauthextension.HtpasswdSettings{ | ||
| File: c.File, | ||
| Inline: c.Inline, | ||
| } | ||
| } | ||
|
|
||
| type ClientAuthConfig struct { | ||
| Username string `alloy:"username,attr"` | ||
| Password string `alloy:"password,attr"` | ||
| } | ||
|
|
||
| func (c ClientAuthConfig) convert() *basicauthextension.ClientAuthSettings { | ||
| if c.Username == "" && c.Password == "" { | ||
| return nil | ||
| } | ||
| return &basicauthextension.ClientAuthSettings{ | ||
| Username: c.Username, | ||
| Password: configopaque.String(c.Password), | ||
| } | ||
| } | ||
|
|
||
| // Arguments configures the otelcol.auth.basic component. | ||
| type Arguments struct { | ||
| Username string `alloy:"username,attr"` | ||
| Password alloytypes.Secret `alloy:"password,attr"` | ||
| Username string `alloy:"username,attr,optional"` // Deprecated: Use ClientAuth instead | ||
| Password alloytypes.Secret `alloy:"password,attr,optional"` // Deprecated: Use ClientAuth instead | ||
|
|
||
| ClientAuth *ClientAuthConfig `alloy:"client_auth,block,optional"` | ||
|
|
||
| Htpasswd *HtpasswdConfig `alloy:"htpasswd,block,optional"` | ||
|
|
||
| // DebugMetrics configures component internal metrics. Optional. | ||
| DebugMetrics otelcolCfg.DebugMetricsArguments `alloy:"debug_metrics,block,optional"` | ||
|
|
@@ -45,23 +82,55 @@ func (args *Arguments) SetToDefault() { | |
| args.DebugMetrics.SetToDefault() | ||
| } | ||
|
|
||
| // Validate implements syntax.Validator | ||
| func (args Arguments) Validate() error { | ||
| // check if no argument was provided | ||
| if args.Username == "" && args.Password == "" && args.Htpasswd == nil && args.ClientAuth == nil { | ||
| return errNoCredentialSource | ||
| } | ||
| // the downstream basicauthextension package supports having both inline | ||
| // and htpasswd files, so we should not error out in case both are | ||
| // provided | ||
|
|
||
| // check if password was not provided when username is provided | ||
| if args.Username != "" && args.Password == "" { | ||
| return errNoPasswordProvided | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // ConvertClient implements auth.Arguments. | ||
| func (args Arguments) ConvertClient() (otelcomponent.Config, error) { | ||
| return &basicauthextension.Config{ | ||
| ClientAuth: &basicauthextension.ClientAuthSettings{ | ||
| Username: args.Username, | ||
| Password: configopaque.String(args.Password), | ||
| }, | ||
| }, nil | ||
| c := &basicauthextension.Config{} | ||
| // If the client config is specified, ignore the deprecated | ||
| // username and password attributes. | ||
| if args.ClientAuth != nil { | ||
| c.ClientAuth = args.ClientAuth.convert() | ||
| return c, nil | ||
| } | ||
|
|
||
| c.ClientAuth = &basicauthextension.ClientAuthSettings{ | ||
| Username: args.Username, | ||
| Password: configopaque.String(args.Password), | ||
| } | ||
| return c, nil | ||
| } | ||
|
|
||
| // ConvertServer implements auth.Arguments. | ||
| func (args Arguments) ConvertServer() (otelcomponent.Config, error) { | ||
| return &basicauthextension.Config{ | ||
| Htpasswd: &basicauthextension.HtpasswdSettings{ | ||
| Inline: fmt.Sprintf("%s:%s", args.Username, args.Password), | ||
| }, | ||
| }, nil | ||
| c := &basicauthextension.Config{ | ||
| Htpasswd: &basicauthextension.HtpasswdSettings{}, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be better if this is only created if |
||
| } | ||
| if args.Htpasswd != nil { | ||
| c.Htpasswd = args.Htpasswd.convert() | ||
| } | ||
| // Keeping this to avoid breaking existing use cases. Remove this for v2 | ||
| if args.Username != "" && args.Password != "" { | ||
| c.Htpasswd.Inline += fmt.Sprintf("\n%s:%s", args.Username, args.Password) | ||
| } | ||
|
|
||
| return c, nil | ||
| } | ||
|
|
||
| // AuthFeatures implements auth.Arguments. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.