diff --git a/x-pack/filebeat/input/o365audit/auth/cert.go b/x-pack/filebeat/input/o365audit/auth/cert.go index 38bb12c85d6..f0b07dc5b9f 100644 --- a/x-pack/filebeat/input/o365audit/auth/cert.go +++ b/x-pack/filebeat/input/o365audit/auth/cert.go @@ -48,7 +48,7 @@ func loadConfigCerts(cfg tlscommon.CertificateConfig) (cert *x509.Certificate, k if err != nil { return nil, nil, errors.Wrapf(err, "error loading X509 certificate from '%s'", cfg.Certificate) } - if tlsCert == nil || len(tlsCert.Certificate) < 1 { + if tlsCert == nil || len(tlsCert.Certificate) == 0 { return nil, nil, fmt.Errorf("no certificates loaded from '%s'", cfg.Certificate) } cert, err = x509.ParseCertificate(tlsCert.Certificate[0]) diff --git a/x-pack/filebeat/input/o365audit/auth/secret.go b/x-pack/filebeat/input/o365audit/auth/secret.go index 38e170cacea..c34d6d48cc6 100644 --- a/x-pack/filebeat/input/o365audit/auth/secret.go +++ b/x-pack/filebeat/input/o365audit/auth/secret.go @@ -9,6 +9,8 @@ import ( "github.com/pkg/errors" ) +// NewProviderFromClientSecret returns a token provider that uses a secret +// for authentication. func NewProviderFromClientSecret(endpoint, resource, applicationID, tenantID, secret string) (p TokenProvider, err error) { oauth, err := adal.NewOAuthConfig(endpoint, tenantID) if err != nil { diff --git a/x-pack/filebeat/input/o365audit/config.go b/x-pack/filebeat/input/o365audit/config.go index 49844c765dc..1701da87190 100644 --- a/x-pack/filebeat/input/o365audit/config.go +++ b/x-pack/filebeat/input/o365audit/config.go @@ -27,17 +27,14 @@ type Config struct { // TenantID (aka. Directory ID) is a list of tenants for which to fetch // the audit logs. This can be a string or a list of strings. - TenantID interface{} `config:"tenant_id,replace" validate:"required"` + TenantID stringList `config:"tenant_id,replace" validate:"required"` // Content-Type is a list of content-types to fetch. // This can be a string or a list of strings. - ContentType interface{} `config:"content_type,replace"` + ContentType stringList `config:"content_type,replace"` // API contains settings to adapt to changes on the API. API APIConfig `config:"api"` - - tenants []string - contentTypes []string } // APIConfig contains advanced settings that are only supposed to be changed @@ -149,36 +146,32 @@ func (c *Config) Validate() (err error) { return errors.Wrap(err, "invalid certificate config") } } - if c.tenants, err = asStringList(c.TenantID); err != nil { - return errors.Wrap(err, "error validating tenant_id") - } - if c.contentTypes, err = asStringList(c.ContentType); err != nil { - return errors.Wrap(err, "error validating content_type") - } return nil } -// A helper to allow defining a field either as a string or a list of strings. -func asStringList(value interface{}) (list []string, err error) { +type stringList []string + +// Unpack populates the stringList with either a single string value or an array. +func (s *stringList) Unpack(value interface{}) error { switch v := value.(type) { case string: - list = []string{v} + *s = []string{v} case []string: - list = v + *s = v case []interface{}: - list = make([]string, len(v)) + *s = make([]string, len(v)) for idx, ival := range v { str, ok := ival.(string) if !ok { - return nil, fmt.Errorf("string value required. Found %v (type %T) at position %d", + return fmt.Errorf("string value required. Found %v (type %T) at position %d", ival, ival, idx+1) } - list[idx] = str + (*s)[idx] = str } default: - return nil, fmt.Errorf("array of strings required. Found %v (type %T)", value, value) + return fmt.Errorf("array of strings required. Found %v (type %T)", value, value) } - return list, nil + return nil } // NewTokenProvider returns an auth.TokenProvider for the given tenantID. diff --git a/x-pack/filebeat/input/o365audit/input.go b/x-pack/filebeat/input/o365audit/input.go index 4b176aeb482..6985bac012c 100644 --- a/x-pack/filebeat/input/o365audit/input.go +++ b/x-pack/filebeat/input/o365audit/input.go @@ -108,9 +108,9 @@ func newInput( }() pollers := make(map[stream]*poll.Poller) - for _, tenantID := range config.tenants { + for _, tenantID := range config.TenantID { // MaxRequestsPerMinute limitation is per tenant. - delay := time.Duration(len(config.contentTypes)) * time.Minute / time.Duration(config.API.MaxRequestsPerMinute) + delay := time.Duration(len(config.ContentType)) * time.Minute / time.Duration(config.API.MaxRequestsPerMinute) auth, err := config.NewTokenProvider(tenantID) if err != nil { return nil, err @@ -118,7 +118,7 @@ func newInput( if _, err = auth.Token(); err != nil { return nil, errors.Wrapf(err, "unable to acquire authentication token for tenant:%s", tenantID) } - for _, contentType := range config.contentTypes { + for _, contentType := range config.ContentType { key := stream{ tenantID: tenantID, contentType: contentType,