diff --git a/x-pack/filebeat/input/httpjson/config_auth.go b/x-pack/filebeat/input/httpjson/config_auth.go index 71911cd6f46c..b4368f5baa2a 100644 --- a/x-pack/filebeat/input/httpjson/config_auth.go +++ b/x-pack/filebeat/input/httpjson/config_auth.go @@ -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"` @@ -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"` @@ -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(), @@ -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) @@ -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() { @@ -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 != "") { @@ -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") } @@ -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") } diff --git a/x-pack/filebeat/input/httpjson/config_test.go b/x-pack/filebeat/input/httpjson/config_test.go index 2ee8c4276c6a..116ea617e3b1 100644 --- a/x-pack/filebeat/input/httpjson/config_test.go +++ b/x-pack/filebeat/input/httpjson/config_test.go @@ -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{}{