Skip to content

Commit

Permalink
x-pack/filebeat/httpjson: autodetect authentication style and allow e…
Browse files Browse the repository at this point in the history
…mpty secrets (#33342)

Allow automatic OAuth2 style detection and do not require a non-empty
client secret, though do require it to be explicitly empty if an empty
secret is needed.

Co-authored-by: Dan Kortschak <[email protected]>
  • Loading branch information
p-leh and efd6 committed Oct 25, 2022
1 parent 951ef08 commit 5dd5e88
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
25 changes: 15 additions & 10 deletions x-pack/filebeat/input/httpjson/config_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import (
"github.com/elastic/beats/v7/libbeat/common"
)

// authStyleInParams sends the "client_id" and "client_secret" in the POST body as application/x-www-form-urlencoded parameters.
const authStyleInParams = 1

type authConfig struct {
Basic *basicAuthConfig `config:"basic"`
OAuth2 *oAuth2Config `config:"oauth2"`
Expand Down Expand Up @@ -84,7 +81,7 @@ type oAuth2Config struct {

// common oauth fields
ClientID string `config:"client.id"`
ClientSecret string `config:"client.secret"`
ClientSecret *string `config:"client.secret"`
EndpointParams map[string][]string `config:"endpoint_params"`
Password string `config:"password"`
Provider oAuth2Provider `config:"provider"`
Expand Down Expand Up @@ -114,7 +111,7 @@ func (o *oAuth2Config) isEnabled() bool {
func (o *oAuth2Config) clientCredentialsGrant(ctx context.Context, _ *http.Client) *http.Client {
creds := clientcredentials.Config{
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
ClientSecret: maybeString(o.ClientSecret),
TokenURL: o.getTokenURL(),
Scopes: o.Scopes,
EndpointParams: o.getEndpointParams(),
Expand All @@ -131,10 +128,10 @@ func (o *oAuth2Config) client(ctx context.Context, client *http.Client) (*http.C
if o.User != "" || o.Password != "" {
conf := &oauth2.Config{
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
ClientSecret: maybeString(o.ClientSecret),
Endpoint: oauth2.Endpoint{
TokenURL: o.TokenURL,
AuthStyle: authStyleInParams,
AuthStyle: oauth2.AuthStyleAutoDetect,
},
}
token, err := conf.PasswordCredentialsToken(ctx, o.User, o.Password)
Expand Down Expand Up @@ -167,6 +164,14 @@ func (o *oAuth2Config) client(ctx context.Context, client *http.Client) (*http.C
}
}

// maybeString returns the string pointed to by p or "" if p in nil.
func maybeString(p *string) string {
if p == nil {
return ""
}
return *p
}

// getTokenURL returns the TokenURL.
func (o *oAuth2Config) getTokenURL() string {
switch o.getProvider() {
Expand Down Expand Up @@ -211,7 +216,7 @@ func (o *oAuth2Config) Validate() error {
case oAuth2ProviderGoogle:
return o.validateGoogleProvider()
case oAuth2ProviderDefault:
if o.TokenURL == "" || o.ClientID == "" || o.ClientSecret == "" {
if o.TokenURL == "" || o.ClientID == "" || o.ClientSecret == nil {
return errors.New("both token_url and client credentials must be provided")
}
if (o.User != "" && o.Password == "") || (o.User == "" && o.Password != "") {
Expand All @@ -228,7 +233,7 @@ func (o *oAuth2Config) Validate() error {
var findDefaultGoogleCredentials = google.FindDefaultCredentials

func (o *oAuth2Config) validateGoogleProvider() error {
if o.TokenURL != "" || o.ClientID != "" || o.ClientSecret != "" ||
if o.TokenURL != "" || o.ClientID != "" || o.ClientSecret != nil ||
o.AzureTenantID != "" || o.AzureResource != "" || len(o.EndpointParams) != 0 {
return errors.New("none of token_url and client credentials can be used, use google.credentials_file, google.jwt_file, google.credentials_json or ADC instead")
}
Expand Down Expand Up @@ -295,7 +300,7 @@ func (o *oAuth2Config) validateAzureProvider() error {
if o.TokenURL != "" && o.AzureTenantID != "" {
return errors.New("only one of token_url and tenant_id can be used")
}
if o.ClientID == "" || o.ClientSecret == "" {
if o.ClientID == "" || o.ClientSecret == nil {
return errors.New("client credentials must be provided")
}

Expand Down
26 changes: 26 additions & 0 deletions x-pack/filebeat/input/httpjson/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@ func TestConfigOauth2Validation(t *testing.T) {
"auth.oauth2": map[string]interface{}{},
},
},
{
name: "client credential secret may be empty",
input: map[string]interface{}{
"auth.oauth2": map[string]interface{}{
"enabled": true,
"token_url": "localhost",
"client": map[string]interface{}{
"id": "a_client_id",
"secret": "",
},
},
},
},
{
name: "client credential secret may not be missing",
expectedErr: "both token_url and client credentials must be provided accessing 'auth.oauth2'",
input: map[string]interface{}{
"auth.oauth2": map[string]interface{}{
"enabled": true,
"token_url": "localhost",
"client": map[string]interface{}{
"id": "a_client_id",
},
},
},
},
{
name: "if user and password is set oauth2 must use user-password authentication",
input: map[string]interface{}{
Expand Down

0 comments on commit 5dd5e88

Please sign in to comment.