From 58bbce84e68641f1e0b6b798cd306ed372c9f0a6 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Wed, 26 May 2021 17:40:34 -0400 Subject: [PATCH 01/11] [CLI-169] logs streams CRUD --- internal/auth/auth.go | 1 + internal/auth0/auth0.go | 2 + internal/auth0/log_stream.go | 22 + internal/cli/log_streams.go | 768 +++++++++++++++++++++++++ internal/cli/logs.go | 1 + internal/display/log_streams.go | 87 +++ pkg/auth0-cli-config-generator/main.go | 5 +- 7 files changed, 885 insertions(+), 1 deletion(-) create mode 100644 internal/auth0/log_stream.go create mode 100644 internal/cli/log_streams.go create mode 100644 internal/display/log_streams.go diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 18abad422..64e93587f 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -36,6 +36,7 @@ var requiredScopes = []string{ "read:connections", "update:connections", "read:client_keys", "read:logs", "read:tenant_settings", "read:custom_domains", "read:anomaly_blocks", "delete:anomaly_blocks", + "create:log_streams", "delete:log_streams", "read:log_streams", "update:log_streams", } // RequiredScopes returns the scopes used for login. diff --git a/internal/auth0/auth0.go b/internal/auth0/auth0.go index d519d56dd..c78b0fd0c 100644 --- a/internal/auth0/auth0.go +++ b/internal/auth0/auth0.go @@ -14,6 +14,7 @@ type API struct { Connection ConnectionAPI CustomDomain CustomDomainAPI Log LogAPI + LogStream LogStreamAPI ResourceServer ResourceServerAPI Role RoleAPI Rule RuleAPI @@ -28,6 +29,7 @@ func NewAPI(m *management.Management) *API { Client: m.Client, CustomDomain: m.CustomDomain, Log: m.Log, + LogStream: m.LogStream, ResourceServer: m.ResourceServer, Role: m.Role, Rule: m.Rule, diff --git a/internal/auth0/log_stream.go b/internal/auth0/log_stream.go new file mode 100644 index 000000000..bca2b246e --- /dev/null +++ b/internal/auth0/log_stream.go @@ -0,0 +1,22 @@ +//go:generate mockgen -source=log_stream.go -destination=log_stream_mock.go -package=auth0 + +package auth0 + +import "gopkg.in/auth0.v5/management" + +type LogStreamAPI interface { + // Create a log stream. + Create(ls *management.LogStream, opts ...management.RequestOption) (err error) + + // Read a log stream. + Read(id string, opts ...management.RequestOption) (ls *management.LogStream, err error) + + // Update a log stream. + Update(id string, ls *management.LogStream, opts ...management.RequestOption) (err error) + + // List all log streams. + List(opts ...management.RequestOption) (ls []*management.LogStream, err error) + + // Delete a log stream. + Delete(id string, opts ...management.RequestOption) (err error) +} diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go new file mode 100644 index 000000000..0e238d480 --- /dev/null +++ b/internal/cli/log_streams.go @@ -0,0 +1,768 @@ +package cli + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/auth0/auth0-cli/internal/ansi" + "github.com/auth0/auth0-cli/internal/auth0" + "github.com/auth0/auth0-cli/internal/prompt" + "github.com/spf13/cobra" + "gopkg.in/auth0.v5/management" +) + +const ( + logStreamTypeAmazonEventBridge = "eventbridge" + logStreamTypeAzureEventGrid = "eventgrid" + logStreamTypeHTTP = "http" + logStreamTypeDatadog = "datadog" + logStreamTypeSplunk = "splunk" + logStreamTypeSumo = "sumo" + contentFormatJsonLines = "JSON Lines" + contentFormatJsonArray = "JSON Array" + contentFormatJsonObject = "JSON Object" +) + +var ( + ID = Argument{ + Name: "Log stream ID", + Help: "Log stream ID", + } + logStreamName = Flag{ + Name: "Name", + LongForm: "name", + ShortForm: "n", + Help: "Name of the log stream.", + AlwaysPrompt: true, + } + logStreamType = Flag{ + Name: "Type", + LongForm: "type", + ShortForm: "t", + Help: "Type of the log stream. Possible values: http, eventbridge, eventgrid, datadog, splunk, sumo.", + IsRequired: true, + } + typeOptions = []string{ + "Http", + "Eventbridge", + "Eventgrid", + "Datadog", + "Splunk", + "Sumo", + } + httpEndpoint = Flag{ + Name: "Http Endpoint", + LongForm: "http-endpoint", + Help: "HTTP endpoint.", + } + httpContentType = Flag{ + Name: "Http Content Type", + LongForm: "http-type", + Help: "HTTP Content-Type header.", + AlwaysPrompt: true, + } + httpContentFormat = Flag{ + Name: "Http Content Format", + LongForm: "http-format", + Help: "HTTP Content-Format header.", + AlwaysPrompt: true, + } + contentFormatOptions = []string{ + "JSONARRAY", + "JSONLINES", + "JSONOBJECT", + } + httpAuthorization = Flag{ + Name: "Http Authorization", + LongForm: "http-auth", + Help: "HTTP Authorization header.", + AlwaysPrompt: true, + } + httpCustomHeaders = Flag{ + Name: "Http Custom Headers", + LongForm: "http-header", + Help: "Custom HTTP headers.", + AlwaysPrompt: true, + } + awsAccountID = Flag{ + Name: "AWS Account ID", + LongForm: "eventbridge-id", + Help: "Id of the AWS account.", + } + awsRegion = Flag{ + Name: "AWS Region", + LongForm: "eventbridge-region", + Help: "The region in which eventbridge will be created.", + } + azureSubscriptionID = Flag{ + Name: "Azure Subscription ID", + LongForm: "eventgrid-id", + Help: "Id of the Azure subscription.", + } + azureRegion = Flag{ + Name: "Azure Region", + LongForm: "eventgrid-region", + Help: "The region in which the Azure subscription is hosted.", + } + azureResourceGroup = Flag{ + Name: "Azure Resource Group", + LongForm: "eventgrid-group", + Help: "The name of the Azure resource group.", + } + datadogRegion = Flag{ + Name: "Datadog Region", + LongForm: "datadog-id", + Help: "The region in which datadog dashboard is created.\n" + + "if you are in the datadog EU site ('app.datadoghq.eu'), the Region should be EU otherwise it should be US.", + IsRequired: true, + } + datadogApiKey = Flag{ + Name: "Datadog API Key", + LongForm: "datadog-key", + Help: "Datadog API Key. To obtain a key, see the Datadog Authentication documentation (https://docs.datadoghq.com/api/latest/authentication).", + IsRequired: true, + } + splunkDomain = Flag{ + Name: "Splunk Domain", + LongForm: "splunk-domain", + Help: "The domain name of the splunk instance.", + IsRequired: true, + } + splunkToken = Flag{ + Name: "Splunk Token", + LongForm: "splunk-token", + Help: "Splunk event collector token.", + IsRequired: true, + } + splunkPort = Flag{ + Name: "Splunk Port", + LongForm: "splunk-port", + Help: "The port of the HTTP event collector.", + IsRequired: true, + } + splunkVerifyTLS = Flag{ + Name: "Splunk Verify TLS", + LongForm: "splunk-secure", + Help: "This should be set to 'false' when using self-signed certificates.", + IsRequired: true, + } + sumoLogicSource = Flag{ + Name: "Sumo Logic Source", + LongForm: "sumo-source", + Help: "Generated URL for your defined HTTP source in Sumo Logic.", + IsRequired: true, + } +) + +func logStreamsCmd(cli *cli) *cobra.Command { + cmd := &cobra.Command{ + Use: "streams", + Short: "Manage resources for log streams", + Long: "manage resources for log streams.", + } + + cmd.SetUsageTemplate(resourceUsageTemplate()) + cmd.AddCommand(listLogStreamsCmd(cli)) + cmd.AddCommand(showLogStreamCmd(cli)) + cmd.AddCommand(createLogStreamCmd(cli)) + cmd.AddCommand(updateLogStreamCmd(cli)) + cmd.AddCommand(deleteLogStreamCmd(cli)) + return cmd +} + +func listLogStreamsCmd(cli *cli) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Args: cobra.NoArgs, + Short: "List all log streams", + Long: `List your existing log streams. To create one try: +auth0 logs streams create`, + Example: `auth0 logs streams list +auth0 logs streams ls`, + RunE: func(cmd *cobra.Command, args []string) error { + var list []*management.LogStream + + if err := ansi.Waiting(func() error { + var err error + list, err = cli.api.LogStream.List() + return err + }); err != nil { + return fmt.Errorf("An unexpected error occurred: %w", err) + } + + cli.renderer.LogStreamList(list) + return nil + }, + } + + return cmd +} + +func showLogStreamCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + Type string + } + + cmd := &cobra.Command{ + Use: "show", + Args: cobra.MaximumNArgs(1), + Short: "Show a log stream by id", + Long: "Show an application.", + Example: `auth0 logs streams show +auth0 logs streams show `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := ID.Ask(cmd, &inputs.ID) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + a := &management.LogStream{ID: &inputs.ID} + + if err := ansi.Waiting(func() error { + var err error + a, err = cli.api.LogStream.Read(inputs.ID) + return err + }); err != nil { + return fmt.Errorf("Unable to load application. The Id %v specified doesn't exist", inputs.ID) + } + cli.renderer.LogStreamShow(a) + return nil + }, + } + + return cmd +} + +func createLogStreamCmd(cli *cli) *cobra.Command { + var inputs struct { + Name string + Type string + HttpEndpoint string + HttpContentType string + httpContentFormat string + HttpAuthorization string + HttpCustomHeaders []string + SplunkDomain string + SplunkToken string + SplunkPort string + SplunkVerifyTLS bool + SumoLogicSource string + DatadogAPIKey string + DatadogRegion string + AwsAccountID string + AwsRegion string + AzureSubscriptionID string + AzureRegion string + AzureResourceGroup string + } + + cmd := &cobra.Command{ + Use: "create", + Args: cobra.NoArgs, + Short: "Create a new log stream", + Long: "Create a new log stream.", + Example: `auth0 logs streams create +auth0 logs streams create --name mylogstream +auth0 logs streams create -n mylogstream --type "http"`, + RunE: func(cmd *cobra.Command, args []string) error { + // Prompt for logstream name + if err := logStreamName.Ask(cmd, &inputs.Name, nil); err != nil { + return err + } + + // Prompt for logstream type + if err := logStreamType.Select(cmd, &inputs.Type, typeOptions, nil); err != nil { + return err + } + + logIsHttp := logsTypeFor(inputs.Type) == logStreamTypeHTTP + logIsSplunk := logsTypeFor(inputs.Type) == logStreamTypeSplunk + logIsSumo := logsTypeFor(inputs.Type) == logStreamTypeSumo + logIsDatadog := logsTypeFor(inputs.Type) == logStreamTypeDatadog + logIsEventbridge := logsTypeFor(inputs.Type) == logStreamTypeAmazonEventBridge + logIsEventgrid := logsTypeFor(inputs.Type) == logStreamTypeAzureEventGrid + + // Load values into a fresh logstream instance + ls := &management.LogStream{ + Name: &inputs.Name, + Type: &inputs.Type, + } + + if logIsHttp { + if err := httpEndpoint.Ask(cmd, &inputs.HttpEndpoint, nil); err != nil { + return err + } + if err := httpContentType.Ask(cmd, &inputs.HttpContentType, nil); err != nil { + return err + } + if err := httpContentFormat.Select(cmd, &inputs.httpContentFormat, contentFormatOptions, nil); err != nil { + return err + } + if err := httpAuthorization.Ask(cmd, &inputs.HttpAuthorization, nil); err != nil { + return err + } + if err := httpCustomHeaders.Ask(cmd, &inputs.HttpCustomHeaders, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkHTTP{ + Authorization: &inputs.HttpAuthorization, + ContentType: &inputs.HttpContentType, + ContentFormat: &inputs.httpContentFormat, + Endpoint: &inputs.HttpEndpoint, + CustomHeaders: stringToInterfaceSlice(inputs.HttpCustomHeaders), + } + } + + if logIsSplunk { + if err := splunkDomain.Ask(cmd, &inputs.SplunkDomain, nil); err != nil { + return err + } + if err := splunkToken.Ask(cmd, &inputs.SplunkToken, nil); err != nil { + return err + } + if err := splunkPort.Ask(cmd, &inputs.SplunkPort, nil); err != nil { + return err + } + if err := splunkVerifyTLS.AskBool(cmd, &inputs.SplunkVerifyTLS, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkSplunk{ + Domain: &inputs.SplunkDomain, + Token: &inputs.SplunkToken, + Port: &inputs.SplunkPort, + Secure: &inputs.SplunkVerifyTLS, + } + } + + if logIsSumo { + if err := sumoLogicSource.Ask(cmd, &inputs.SumoLogicSource, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkSumo{ + SourceAddress: &inputs.SumoLogicSource, + } + } + + if logIsDatadog { + if err := datadogApiKey.Ask(cmd, &inputs.DatadogAPIKey, nil); err != nil { + return err + } + if err := datadogRegion.Ask(cmd, &inputs.DatadogRegion, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkDatadog{ + Region: &inputs.DatadogRegion, + APIKey: &inputs.DatadogAPIKey, + } + } + + if logIsEventbridge { + if err := awsAccountID.Ask(cmd, &inputs.AwsAccountID, nil); err != nil { + return err + } + if err := awsRegion.Ask(cmd, &inputs.AwsRegion, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkAmazonEventBridge{ + AccountID: &inputs.AwsAccountID, + Region: &inputs.AwsRegion, + } + } + + if logIsEventgrid { + if err := azureSubscriptionID.Ask(cmd, &inputs.AzureSubscriptionID, nil); err != nil { + return err + } + if err := azureRegion.Ask(cmd, &inputs.AzureRegion, nil); err != nil { + return err + } + if err := azureResourceGroup.Ask(cmd, &inputs.AzureResourceGroup, nil); err != nil { + return err + } + ls.Sink = &management.LogStreamSinkAzureEventGrid{ + SubscriptionID: &inputs.AzureSubscriptionID, + ResourceGroup: &inputs.AzureResourceGroup, + Region: &inputs.AzureRegion, + } + } + + // Create log stream + if err := ansi.Waiting(func() error { + return cli.api.LogStream.Create(ls) + }); err != nil { + return fmt.Errorf("Unable to create log stream: %v", err) + } + + // Render log stream creation specific view + cli.renderer.LogStreamCreate(ls) + return nil + }, + } + + logStreamName.RegisterString(cmd, &inputs.Name, "") + logStreamType.RegisterString(cmd, &inputs.Type, "") + httpEndpoint.RegisterString(cmd, &inputs.HttpEndpoint, "") + httpContentType.RegisterString(cmd, &inputs.HttpContentType, "") + httpContentFormat.RegisterString(cmd, &inputs.httpContentFormat, "") + httpAuthorization.RegisterString(cmd, &inputs.HttpAuthorization, "") + httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) + splunkDomain.RegisterString(cmd, &inputs.SplunkDomain, "") + splunkToken.RegisterString(cmd, &inputs.SplunkToken, "") + splunkPort.RegisterString(cmd, &inputs.SplunkPort, "") + splunkVerifyTLS.RegisterBool(cmd, &inputs.SplunkVerifyTLS, false) + sumoLogicSource.RegisterString(cmd, &inputs.SumoLogicSource, "") + datadogApiKey.RegisterString(cmd, &inputs.DatadogAPIKey, "") + datadogRegion.RegisterString(cmd, &inputs.DatadogRegion, "") + awsAccountID.RegisterString(cmd, &inputs.AwsAccountID, "") + awsRegion.RegisterString(cmd, &inputs.AwsRegion, "") + azureSubscriptionID.RegisterString(cmd, &inputs.AzureSubscriptionID, "") + azureRegion.RegisterString(cmd, &inputs.AzureRegion, "") + azureResourceGroup.RegisterString(cmd, &inputs.AzureResourceGroup, "") + + return cmd +} + +func updateLogStreamCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + Name string + Type string + //Status string + HttpEndpoint string + HttpContentType string + httpContentFormat string + HttpAuthorization string + HttpCustomHeaders []string + SplunkDomain string + SplunkToken string + SplunkPort string + SplunkVerifyTLS bool + SumoLogicSource string + DatadogAPIKey string + DatadogRegion string + } + + cmd := &cobra.Command{ + Use: "update", + Args: cobra.NoArgs, + Short: "Update a new log stream", + Long: "Update a new log stream.", + Example: `auth0 logs streams update +auth0 logs streams update --name mylogstream +auth0 logs streams update -n mylogstream --type "http"`, + RunE: func(cmd *cobra.Command, args []string) error { + var current *management.LogStream + + if len(args) == 0 { + err := ID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + if err := ansi.Waiting(func() error { + var err error + current, err = cli.api.LogStream.Read(inputs.ID) + return err + }); err != nil { + return fmt.Errorf("Unable to load logstreams. The Id %v specified doesn't exist", inputs.ID) + } + + // Prompt for logstream name + if err := logStreamName.AskU(cmd, &inputs.Name, current.Name); err != nil { + return err + } + + logIsHttp := auth0.StringValue(current.Type) == logStreamTypeHTTP + logIsSplunk := auth0.StringValue(current.Type) == logStreamTypeSplunk + logIsSumo := auth0.StringValue(current.Type) == logStreamTypeSumo + logIsDatadog := auth0.StringValue(current.Type) == logStreamTypeDatadog + + // Load values into a fresh logstream instance + ls := &management.LogStream{ + Status: current.Status, + } + + if logIsDatadog { + s := &management.LogStreamSinkDatadog{} + + res := cli.getLogStreamSink(current.GetID()) + if err := json.Unmarshal([]byte(res), s); err != nil { + fmt.Println(err) + } + + if err := datadogApiKey.AskU(cmd, &inputs.DatadogAPIKey, s.APIKey); err != nil { + return err + } + if err := datadogRegion.AskU(cmd, &inputs.DatadogRegion, s.Region); err != nil { + return err + } + + if len(inputs.DatadogAPIKey) > 0 { + s.APIKey = &inputs.DatadogAPIKey + } + if len(inputs.DatadogRegion) > 0 { + s.Region = &inputs.DatadogRegion + } + + ls.Sink = &management.LogStreamSinkDatadog{ + Region: s.Region, + APIKey: s.APIKey, + } + } + + if logIsSumo { + s := &management.LogStreamSinkSumo{} + + res := cli.getLogStreamSink(current.GetID()) + if err := json.Unmarshal([]byte(res), s); err != nil { + fmt.Println(err) + } + if err := sumoLogicSource.AskU(cmd, &inputs.SumoLogicSource, s.SourceAddress); err != nil { + return err + } + + if len(inputs.SumoLogicSource) > 0 { + s.SourceAddress = &inputs.SumoLogicSource + } + ls.Sink = &management.LogStreamSinkSumo{ + SourceAddress: s.SourceAddress, + } + } + + if logIsSplunk { + s := &management.LogStreamSinkSplunk{} + + res := cli.getLogStreamSink(current.GetID()) + if err := json.Unmarshal([]byte(res), s); err != nil { + fmt.Println(err) + } + + if err := splunkDomain.AskU(cmd, &inputs.SplunkDomain, s.Domain); err != nil { + return err + } + if err := splunkToken.AskU(cmd, &inputs.SplunkToken, s.Token); err != nil { + return err + } + if err := splunkPort.AskU(cmd, &inputs.SplunkPort, s.Port); err != nil { + return err + } + if err := splunkVerifyTLS.AskBoolU(cmd, &inputs.SplunkVerifyTLS, s.Secure); err != nil { + return err + } + + if len(inputs.SplunkDomain) > 0 { + s.Domain = &inputs.SplunkDomain + } + if len(inputs.SplunkToken) > 0 { + s.Token = &inputs.SplunkToken + } + if len(inputs.SplunkPort) > 0 { + s.Port = &inputs.SplunkPort + } + if !splunkVerifyTLS.IsSet(cmd) { + s.Secure = auth0.Bool(inputs.SplunkVerifyTLS) + } + + ls.Sink = &management.LogStreamSinkSplunk{ + Domain: s.Domain, + Token: s.Token, + Port: s.Port, + Secure: s.Secure, + } + } + + if logIsHttp { + s := &management.LogStreamSinkHTTP{} + + res := cli.getLogStreamSink(current.GetID()) + if err := json.Unmarshal([]byte(res), s); err != nil { + fmt.Println(err) + } + if err := httpEndpoint.AskU(cmd, &inputs.HttpEndpoint, s.Endpoint); err != nil { + return err + } + + if err := httpContentType.AskU(cmd, &inputs.HttpContentType, s.ContentType); err != nil { + return err + } + if err := httpContentFormat.SelectU(cmd, &inputs.httpContentFormat, contentFormatOptions, s.ContentFormat); err != nil { + return err + } + if err := httpAuthorization.AskU(cmd, &inputs.HttpAuthorization, s.Authorization); err != nil { + return err + } + + if len(inputs.HttpEndpoint) > 0 { + s.Endpoint = &inputs.HttpEndpoint + } + if len(inputs.HttpContentType) > 0 { + s.ContentType = &inputs.HttpContentType + } + if len(inputs.httpContentFormat) > 0 { + s.ContentFormat = &inputs.httpContentFormat + } + if len(inputs.HttpAuthorization) > 0 { + s.Authorization = &inputs.HttpAuthorization + } + + ls.Sink = &management.LogStreamSinkHTTP{ + Authorization: s.Authorization, + ContentType: s.ContentType, + ContentFormat: s.ContentFormat, + Endpoint: s.Endpoint, + } + } + + if len(inputs.Name) == 0 { + ls.Name = current.Name + } else { + ls.Name = &inputs.Name + } + + // Update a log stream + if err := ansi.Waiting(func() error { + return cli.api.LogStream.Update(current.GetID(), ls) + }); err != nil { + return fmt.Errorf("Unable to update log stream: %v", err) + } + + //// Render log stream creation specific view + cli.renderer.LogStreamUpdate(ls) + return nil + }, + } + + logStreamName.RegisterStringU(cmd, &inputs.Name, "") + logStreamType.RegisterStringU(cmd, &inputs.Type, "") + httpEndpoint.RegisterStringU(cmd, &inputs.HttpEndpoint, "") + httpContentType.RegisterStringU(cmd, &inputs.HttpContentType, "") + httpContentFormat.RegisterStringU(cmd, &inputs.httpContentFormat, "") + httpAuthorization.RegisterStringU(cmd, &inputs.HttpAuthorization, "") + splunkDomain.RegisterStringU(cmd, &inputs.SplunkDomain, "") + splunkToken.RegisterStringU(cmd, &inputs.SplunkToken, "") + splunkPort.RegisterStringU(cmd, &inputs.SplunkPort, "") + splunkVerifyTLS.RegisterBoolU(cmd, &inputs.SplunkVerifyTLS, false) + sumoLogicSource.RegisterStringU(cmd, &inputs.SumoLogicSource, "") + datadogApiKey.RegisterStringU(cmd, &inputs.DatadogAPIKey, "") + datadogRegion.RegisterStringU(cmd, &inputs.DatadogRegion, "") + + return cmd +} + +func deleteLogStreamCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "delete", + Args: cobra.MaximumNArgs(1), + Short: "Delete a log stream", + Long: "Delete a log stream.", + Example: `auth0 logs streams delete +auth0 logs streams delete `, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := ID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + if !cli.force && canPrompt(cmd) { + if confirmed := prompt.Confirm("Are you sure you want to proceed?"); !confirmed { + return nil + } + } + + return ansi.Spinner("Deleting Log Stream", func() error { + _, err := cli.api.LogStream.Read(inputs.ID) + + if err != nil { + return fmt.Errorf("Unable to delete log strean. The specified Id: %v doesn't exist", inputs.ID) + } + + return cli.api.LogStream.Delete(inputs.ID) + }) + }, + } + + return cmd +} + +func (c *cli) logTypePickerOptions() []string { + var res []string + + list, err := c.api.LogStream.List() + if err != nil { + fmt.Println(err) + } + for _, ls := range list { + res = append(res, ls.GetType()) + } + + return res +} + +func (c *cli) logStreamPickerOptions() (pickerOptions, error) { + list, err := c.api.LogStream.List() + if err != nil { + return nil, err + } + + var opts pickerOptions + + for _, c := range list { + value := c.GetID() + label := fmt.Sprintf("%s %s", c.GetName(), ansi.Faint("("+value+")")) + opts = append(opts, pickerOption{value: value, label: label}) + } + + if len(opts) == 0 { + return nil, errNoRoles + } + + return opts, nil +} + +func logsTypeFor(v string) string { + switch strings.ToLower(v) { + case "http": + return logStreamTypeHTTP + case "eventbridge", "amazon eventbridge": + return logStreamTypeAmazonEventBridge + case "eventgrid", "azure eventgrid": + return logStreamTypeAzureEventGrid + case "datadog": + return logStreamTypeDatadog + case "splunk": + return logStreamTypeSplunk + case "sumo": + return logStreamTypeSumo + default: + return v + } +} + +// getLogStreamSink +func (c *cli) getLogStreamSink(ID string) string { + conn, err := c.api.LogStream.Read(ID) + if err != nil { + fmt.Println(err) + } + res := fmt.Sprintln(conn.Sink) + + return res +} diff --git a/internal/cli/logs.go b/internal/cli/logs.go index 0cbee9cf4..d028a652e 100644 --- a/internal/cli/logs.go +++ b/internal/cli/logs.go @@ -35,6 +35,7 @@ func logsCmd(cli *cli) *cobra.Command { cmd.SetUsageTemplate(resourceUsageTemplate()) cmd.AddCommand(listLogsCmd(cli)) cmd.AddCommand(tailLogsCmd(cli)) + cmd.AddCommand(logStreamsCmd(cli)) return cmd } diff --git a/internal/display/log_streams.go b/internal/display/log_streams.go new file mode 100644 index 000000000..65edba26c --- /dev/null +++ b/internal/display/log_streams.go @@ -0,0 +1,87 @@ +package display + +import ( + "github.com/auth0/auth0-cli/internal/ansi" + "gopkg.in/auth0.v5/management" +) + +type logStreamView struct { + ID string + Name string + Type string + Status string + //Sink interface{} +} + +func (v *logStreamView) AsTableHeader() []string { + return []string{"ID", "Name", "Type", "Status"} +} + +func (v *logStreamView) AsTableRow() []string { + return []string{ + ansi.Faint(v.ID), + v.Name, + v.Type, + v.Status, + //fmt.Sprintln(v.Sink), + } +} + +func (v *logStreamView) KeyValues() [][]string { + return [][]string{ + []string{"ID", ansi.Faint(v.ID)}, + []string{"NAME", v.Name}, + []string{"TYPE", v.Type}, + []string{"STATUS", v.Status}, + //[]string{"SINK", fmt.Sprintln(v.Sink)}, + } +} + +func (r *Renderer) LogStreamList(logs []*management.LogStream) { + resource := "log streams" + + r.Heading(resource) + + if len(logs) == 0 { + r.EmptyState(resource) + r.Infof("use 'auth0 logs streams create' to create one") + return + } + + var res []View + for _, ls := range logs { + res = append(res, &logStreamView{ + ID: ansi.Faint(ls.GetID()), + Name: ls.GetName(), + Type: ls.GetType(), + Status: ls.GetStatus(), + }) + } + + r.Results(res) +} + +func (r *Renderer) LogStreamShow(logs *management.LogStream) { + r.Heading("log streams") + r.logStreamResult(logs) +} + +func (r *Renderer) LogStreamCreate(logs *management.LogStream) { + r.Heading("log streams created") + r.logStreamResult(logs) +} + +func (r *Renderer) LogStreamUpdate(logs *management.LogStream) { + r.Heading("log streams updated") + r.logStreamResult(logs) +} + +func (r *Renderer) logStreamResult(logs *management.LogStream) { + r.Result(&logStreamView{ + ID: ansi.Faint(logs.GetID()), + Name: logs.GetName(), + Type: logs.GetType(), + Status: logs.GetStatus(), + //Sink: logs.Sink, + }) +} diff --git a/pkg/auth0-cli-config-generator/main.go b/pkg/auth0-cli-config-generator/main.go index 6d8bef902..3ba68da1d 100644 --- a/pkg/auth0-cli-config-generator/main.go +++ b/pkg/auth0-cli-config-generator/main.go @@ -32,11 +32,14 @@ var requiredScopes = []string{ // "offline_access", // <-- to get a refresh token. "create:clients", "delete:clients", "read:clients", "update:clients", "create:resource_servers", "delete:resource_servers", "read:resource_servers", "update:resource_servers", + "create:roles", "delete:roles", "read:roles", "update:roles", "create:rules", "delete:rules", "read:rules", "update:rules", - "read:client_keys", "read:logs", "read:connections", "update:connections", "create:users", "delete:users", "read:users", "update:users", "read:branding", "update:branding", + "read:connections", "update:connections", "read:client_keys", "read:logs", "read:tenant_settings", "read:custom_domains", + "read:anomaly_blocks", "delete:anomaly_blocks", + "create:log_streams", "delete:log_streams", "read:log_streams", "update:log_streams", } func (p params) validate() error { From b75f164dfb9371e30dd76c839f391e9a2fceb837 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Thu, 27 May 2021 12:05:23 -0400 Subject: [PATCH 02/11] [CLI-169] logs streams refactor: add open command --- internal/cli/log_streams.go | 144 +++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 50 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 0e238d480..19b6db1c5 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -19,13 +19,10 @@ const ( logStreamTypeDatadog = "datadog" logStreamTypeSplunk = "splunk" logStreamTypeSumo = "sumo" - contentFormatJsonLines = "JSON Lines" - contentFormatJsonArray = "JSON Array" - contentFormatJsonObject = "JSON Object" ) var ( - ID = Argument{ + logsID = Argument{ Name: "Log stream ID", Help: "Log stream ID", } @@ -59,20 +56,15 @@ var ( httpContentType = Flag{ Name: "Http Content Type", LongForm: "http-type", - Help: "HTTP Content-Type header.", + Help: "HTTP Content-Type header. Possible values: application/json.", AlwaysPrompt: true, } httpContentFormat = Flag{ Name: "Http Content Format", LongForm: "http-format", - Help: "HTTP Content-Format header.", + Help: "HTTP Content-Format header. Possible values: JSONLINES, JSONARRAY, JSONOBJECT.", AlwaysPrompt: true, } - contentFormatOptions = []string{ - "JSONARRAY", - "JSONLINES", - "JSONOBJECT", - } httpAuthorization = Flag{ Name: "Http Authorization", LongForm: "http-auth", @@ -168,6 +160,8 @@ func logStreamsCmd(cli *cli) *cobra.Command { cmd.AddCommand(createLogStreamCmd(cli)) cmd.AddCommand(updateLogStreamCmd(cli)) cmd.AddCommand(deleteLogStreamCmd(cli)) + cmd.AddCommand(openLogStreamsCmd(cli)) + return cmd } @@ -215,7 +209,7 @@ func showLogStreamCmd(cli *cli) *cobra.Command { auth0 logs streams show `, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { - err := ID.Ask(cmd, &inputs.ID) + err := logsID.Ask(cmd, &inputs.ID) if err != nil { return err } @@ -270,14 +264,16 @@ func createLogStreamCmd(cli *cli) *cobra.Command { Long: "Create a new log stream.", Example: `auth0 logs streams create auth0 logs streams create --name mylogstream -auth0 logs streams create -n mylogstream --type "http"`, +auth0 logs streams create -n mylogstream -t http --http-type application/json --http-format JSONLINES --http-auth 1343434 +auth0 logs streams create -n mydatadog -t datadog --datadog-key 9999999 --datadog-id us +auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 999999999999 --eventbridge-region us-east-1`, RunE: func(cmd *cobra.Command, args []string) error { - // Prompt for logstream name + // Prompt for log stream name if err := logStreamName.Ask(cmd, &inputs.Name, nil); err != nil { return err } - // Prompt for logstream type + // Prompt for log stream type if err := logStreamType.Select(cmd, &inputs.Type, typeOptions, nil); err != nil { return err } @@ -289,12 +285,13 @@ auth0 logs streams create -n mylogstream --type "http"`, logIsEventbridge := logsTypeFor(inputs.Type) == logStreamTypeAmazonEventBridge logIsEventgrid := logsTypeFor(inputs.Type) == logStreamTypeAzureEventGrid - // Load values into a fresh logstream instance + // Load values into a fresh log stream instance ls := &management.LogStream{ Name: &inputs.Name, - Type: &inputs.Type, + Type: auth0.String(logsTypeFor(inputs.Type)), } + // Prompt for http sink details if type is http if logIsHttp { if err := httpEndpoint.Ask(cmd, &inputs.HttpEndpoint, nil); err != nil { return err @@ -302,24 +299,25 @@ auth0 logs streams create -n mylogstream --type "http"`, if err := httpContentType.Ask(cmd, &inputs.HttpContentType, nil); err != nil { return err } - if err := httpContentFormat.Select(cmd, &inputs.httpContentFormat, contentFormatOptions, nil); err != nil { + if err := httpContentFormat.Ask(cmd, &inputs.httpContentFormat, nil); err != nil { return err } if err := httpAuthorization.Ask(cmd, &inputs.HttpAuthorization, nil); err != nil { return err } - if err := httpCustomHeaders.Ask(cmd, &inputs.HttpCustomHeaders, nil); err != nil { - return err - } + //if err := httpCustomHeaders.Ask(cmd, &inputs.HttpCustomHeaders, nil); err != nil { + // return err + //} ls.Sink = &management.LogStreamSinkHTTP{ Authorization: &inputs.HttpAuthorization, ContentType: &inputs.HttpContentType, ContentFormat: &inputs.httpContentFormat, Endpoint: &inputs.HttpEndpoint, - CustomHeaders: stringToInterfaceSlice(inputs.HttpCustomHeaders), + //CustomHeaders: stringToInterfaceSlice(inputs.HttpCustomHeaders), } } + // Prompt for splunk sink details if log stream type is splunk if logIsSplunk { if err := splunkDomain.Ask(cmd, &inputs.SplunkDomain, nil); err != nil { return err @@ -341,6 +339,7 @@ auth0 logs streams create -n mylogstream --type "http"`, } } + // Prompt for sumo sink details if log stream type is sumo if logIsSumo { if err := sumoLogicSource.Ask(cmd, &inputs.SumoLogicSource, nil); err != nil { return err @@ -350,6 +349,7 @@ auth0 logs streams create -n mylogstream --type "http"`, } } + // Prompt for datadog sink details if log stream type is datadog if logIsDatadog { if err := datadogApiKey.Ask(cmd, &inputs.DatadogAPIKey, nil); err != nil { return err @@ -363,6 +363,7 @@ auth0 logs streams create -n mylogstream --type "http"`, } } + // Prompt for eventbridge sink details if log stream type is eventbridge if logIsEventbridge { if err := awsAccountID.Ask(cmd, &inputs.AwsAccountID, nil); err != nil { return err @@ -376,6 +377,7 @@ auth0 logs streams create -n mylogstream --type "http"`, } } + // Prompt for eventgrid sink details if log stream type is eventgrid if logIsEventgrid { if err := azureSubscriptionID.Ask(cmd, &inputs.AzureSubscriptionID, nil); err != nil { return err @@ -412,7 +414,7 @@ auth0 logs streams create -n mylogstream --type "http"`, httpContentType.RegisterString(cmd, &inputs.HttpContentType, "") httpContentFormat.RegisterString(cmd, &inputs.httpContentFormat, "") httpAuthorization.RegisterString(cmd, &inputs.HttpAuthorization, "") - httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) + //httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) splunkDomain.RegisterString(cmd, &inputs.SplunkDomain, "") splunkToken.RegisterString(cmd, &inputs.SplunkToken, "") splunkPort.RegisterString(cmd, &inputs.SplunkPort, "") @@ -431,37 +433,39 @@ auth0 logs streams create -n mylogstream --type "http"`, func updateLogStreamCmd(cli *cli) *cobra.Command { var inputs struct { - ID string - Name string - Type string - //Status string - HttpEndpoint string - HttpContentType string - httpContentFormat string - HttpAuthorization string - HttpCustomHeaders []string - SplunkDomain string - SplunkToken string - SplunkPort string - SplunkVerifyTLS bool - SumoLogicSource string - DatadogAPIKey string - DatadogRegion string + ID string + Name string + Type string + HttpEndpoint string + HttpContentType string + httpContentFormat string + HttpAuthorization string + HttpCustomHeaders []string + SplunkDomain string + SplunkToken string + SplunkPort string + SplunkVerifyTLS bool + SumoLogicSource string + DatadogAPIKey string + DatadogRegion string } cmd := &cobra.Command{ Use: "update", - Args: cobra.NoArgs, + Args: cobra.MaximumNArgs(1), Short: "Update a new log stream", Long: "Update a new log stream.", Example: `auth0 logs streams update -auth0 logs streams update --name mylogstream -auth0 logs streams update -n mylogstream --type "http"`, +auth0 logs streams update --name mylogstream +auth0 logs streams update -n mylogstream --type http +auth0 logs streams update -n mylogstream -t http --http-type application/json --http-format JSONLINES +auth0 logs streams update -n mydatadog -t datadog --datadog-key 9999999 --datadog-id us +auth0 logs streams update -n myeventbridge -t eventbridge`, RunE: func(cmd *cobra.Command, args []string) error { var current *management.LogStream if len(args) == 0 { - err := ID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) + err := logsID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) if err != nil { return err } @@ -469,6 +473,7 @@ auth0 logs streams update -n mylogstream --type "http"`, inputs.ID = args[0] } + // Load log stream by id if err := ansi.Waiting(func() error { var err error current, err = cli.api.LogStream.Read(inputs.ID) @@ -477,7 +482,7 @@ auth0 logs streams update -n mylogstream --type "http"`, return fmt.Errorf("Unable to load logstreams. The Id %v specified doesn't exist", inputs.ID) } - // Prompt for logstream name + // Prompt for log stream name if err := logStreamName.AskU(cmd, &inputs.Name, current.Name); err != nil { return err } @@ -487,11 +492,12 @@ auth0 logs streams update -n mylogstream --type "http"`, logIsSumo := auth0.StringValue(current.Type) == logStreamTypeSumo logIsDatadog := auth0.StringValue(current.Type) == logStreamTypeDatadog - // Load values into a fresh logstream instance + // Load values into a fresh log stream instance ls := &management.LogStream{ Status: current.Status, } + // Prompt for datadog sink details if log stream type is datadog if logIsDatadog { s := &management.LogStreamSinkDatadog{} @@ -520,6 +526,7 @@ auth0 logs streams update -n mylogstream --type "http"`, } } + // Prompt for sumo sink details if log stream type is sumo if logIsSumo { s := &management.LogStreamSinkSumo{} @@ -539,6 +546,7 @@ auth0 logs streams update -n mylogstream --type "http"`, } } + // Prompt for splunk sink details if log stream type is splunk if logIsSplunk { s := &management.LogStreamSinkSplunk{} @@ -581,6 +589,7 @@ auth0 logs streams update -n mylogstream --type "http"`, } } + // Prompt for http sink details if type is http if logIsHttp { s := &management.LogStreamSinkHTTP{} @@ -591,11 +600,10 @@ auth0 logs streams update -n mylogstream --type "http"`, if err := httpEndpoint.AskU(cmd, &inputs.HttpEndpoint, s.Endpoint); err != nil { return err } - if err := httpContentType.AskU(cmd, &inputs.HttpContentType, s.ContentType); err != nil { return err } - if err := httpContentFormat.SelectU(cmd, &inputs.httpContentFormat, contentFormatOptions, s.ContentFormat); err != nil { + if err := httpContentFormat.AskU(cmd, &inputs.httpContentFormat, s.ContentFormat); err != nil { return err } if err := httpAuthorization.AskU(cmd, &inputs.HttpAuthorization, s.Authorization); err != nil { @@ -636,7 +644,7 @@ auth0 logs streams update -n mylogstream --type "http"`, return fmt.Errorf("Unable to update log stream: %v", err) } - //// Render log stream creation specific view + // Render log stream update specific view cli.renderer.LogStreamUpdate(ls) return nil }, @@ -673,7 +681,7 @@ func deleteLogStreamCmd(cli *cli) *cobra.Command { auth0 logs streams delete `, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { - err := ID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) + err := logsID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) if err != nil { return err } @@ -691,7 +699,7 @@ auth0 logs streams delete `, _, err := cli.api.LogStream.Read(inputs.ID) if err != nil { - return fmt.Errorf("Unable to delete log strean. The specified Id: %v doesn't exist", inputs.ID) + return fmt.Errorf("Unable to delete log stream. The specified Id: %v doesn't exist", inputs.ID) } return cli.api.LogStream.Delete(inputs.ID) @@ -702,6 +710,42 @@ auth0 logs streams delete `, return cmd } +func openLogStreamsCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + } + + cmd := &cobra.Command{ + Use: "open", + Args: cobra.MaximumNArgs(1), + Short: "Open log stream settings page in Auth0 Manage", + Long: "Open log stream settings page in Auth0 Manage.", + Example: "auth0 logs streams open ", + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + err := logsID.Pick(cmd, &inputs.ID, cli.logStreamPickerOptions) + if err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + openManageURL(cli, cli.config.DefaultTenant, formatLogStreamSettingsPath(inputs.ID)) + return nil + }, + } + + return cmd +} + +func formatLogStreamSettingsPath(id string) string { + if len(id) == 0 { + return "" + } + return fmt.Sprintf("log-streams/%s/settings", id) +} + func (c *cli) logTypePickerOptions() []string { var res []string From ef275783e29446e037c5f74ff81dedfdf1f320b6 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Thu, 27 May 2021 12:08:05 -0400 Subject: [PATCH 03/11] [CLI-169] logs streams refactor: clean up --- internal/cli/log_streams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 19b6db1c5..822ab0bdb 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -414,7 +414,7 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 httpContentType.RegisterString(cmd, &inputs.HttpContentType, "") httpContentFormat.RegisterString(cmd, &inputs.httpContentFormat, "") httpAuthorization.RegisterString(cmd, &inputs.HttpAuthorization, "") - //httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) + httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) splunkDomain.RegisterString(cmd, &inputs.SplunkDomain, "") splunkToken.RegisterString(cmd, &inputs.SplunkToken, "") splunkPort.RegisterString(cmd, &inputs.SplunkPort, "") From 7bf5cfc30a75f7431ccd9fdc76da7016bc573bde Mon Sep 17 00:00:00 2001 From: bright-poku Date: Thu, 27 May 2021 12:10:40 -0400 Subject: [PATCH 04/11] [CLI-169] logs streams refactor: remove unused functions --- internal/cli/log_streams.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 822ab0bdb..63ad51668 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -746,20 +746,6 @@ func formatLogStreamSettingsPath(id string) string { return fmt.Sprintf("log-streams/%s/settings", id) } -func (c *cli) logTypePickerOptions() []string { - var res []string - - list, err := c.api.LogStream.List() - if err != nil { - fmt.Println(err) - } - for _, ls := range list { - res = append(res, ls.GetType()) - } - - return res -} - func (c *cli) logStreamPickerOptions() (pickerOptions, error) { list, err := c.api.LogStream.List() if err != nil { From 019e19b04f49222c8d6b8120c206149e456502ce Mon Sep 17 00:00:00 2001 From: bright-poku Date: Thu, 27 May 2021 12:47:03 -0400 Subject: [PATCH 05/11] [CLI-169] logs streams refactor --- internal/cli/log_streams.go | 113 ++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 63ad51668..72acee525 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -49,9 +49,10 @@ var ( "Sumo", } httpEndpoint = Flag{ - Name: "Http Endpoint", - LongForm: "http-endpoint", - Help: "HTTP endpoint.", + Name: "Http Endpoint", + LongForm: "http-endpoint", + Help: "HTTP endpoint.", + IsRequired: true, } httpContentType = Flag{ Name: "Http Content Type", @@ -71,36 +72,35 @@ var ( Help: "HTTP Authorization header.", AlwaysPrompt: true, } - httpCustomHeaders = Flag{ - Name: "Http Custom Headers", - LongForm: "http-header", - Help: "Custom HTTP headers.", - AlwaysPrompt: true, - } awsAccountID = Flag{ - Name: "AWS Account ID", - LongForm: "eventbridge-id", - Help: "Id of the AWS account.", + Name: "AWS Account ID", + LongForm: "eventbridge-id", + Help: "Id of the AWS account.", + IsRequired: true, } awsRegion = Flag{ - Name: "AWS Region", - LongForm: "eventbridge-region", - Help: "The region in which eventbridge will be created.", + Name: "AWS Region", + LongForm: "eventbridge-region", + Help: "The region in which eventbridge will be created.", + IsRequired: true, } azureSubscriptionID = Flag{ - Name: "Azure Subscription ID", - LongForm: "eventgrid-id", - Help: "Id of the Azure subscription.", + Name: "Azure Subscription ID", + LongForm: "eventgrid-id", + Help: "Id of the Azure subscription.", + IsRequired: true, } azureRegion = Flag{ - Name: "Azure Region", - LongForm: "eventgrid-region", - Help: "The region in which the Azure subscription is hosted.", + Name: "Azure Region", + LongForm: "eventgrid-region", + Help: "The region in which the Azure subscription is hosted.", + IsRequired: true, } azureResourceGroup = Flag{ - Name: "Azure Resource Group", - LongForm: "eventgrid-group", - Help: "The name of the Azure resource group.", + Name: "Azure Resource Group", + LongForm: "eventgrid-group", + Help: "The name of the Azure resource group.", + IsRequired: true, } datadogRegion = Flag{ Name: "Datadog Region", @@ -128,16 +128,14 @@ var ( IsRequired: true, } splunkPort = Flag{ - Name: "Splunk Port", - LongForm: "splunk-port", - Help: "The port of the HTTP event collector.", - IsRequired: true, + Name: "Splunk Port", + LongForm: "splunk-port", + Help: "The port of the HTTP event collector.", } splunkVerifyTLS = Flag{ - Name: "Splunk Verify TLS", - LongForm: "splunk-secure", - Help: "This should be set to 'false' when using self-signed certificates.", - IsRequired: true, + Name: "Splunk Verify TLS", + LongForm: "splunk-secure", + Help: "This should be set to 'false' when using self-signed certificates.", } sumoLogicSource = Flag{ Name: "Sumo Logic Source", @@ -242,7 +240,6 @@ func createLogStreamCmd(cli *cli) *cobra.Command { HttpContentType string httpContentFormat string HttpAuthorization string - HttpCustomHeaders []string SplunkDomain string SplunkToken string SplunkPort string @@ -263,10 +260,10 @@ func createLogStreamCmd(cli *cli) *cobra.Command { Short: "Create a new log stream", Long: "Create a new log stream.", Example: `auth0 logs streams create -auth0 logs streams create --name mylogstream auth0 logs streams create -n mylogstream -t http --http-type application/json --http-format JSONLINES --http-auth 1343434 auth0 logs streams create -n mydatadog -t datadog --datadog-key 9999999 --datadog-id us -auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 999999999999 --eventbridge-region us-east-1`, +auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 999999999999 --eventbridge-region us-east-1 +auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.com --splunk-token 12a34ab5-c6d7-8901-23ef-456b7c89d0c1 --splunk-port 8080 --splunk-secure=true`, RunE: func(cmd *cobra.Command, args []string) error { // Prompt for log stream name if err := logStreamName.Ask(cmd, &inputs.Name, nil); err != nil { @@ -296,24 +293,24 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := httpEndpoint.Ask(cmd, &inputs.HttpEndpoint, nil); err != nil { return err } + if err := httpContentType.Ask(cmd, &inputs.HttpContentType, nil); err != nil { return err } + if err := httpContentFormat.Ask(cmd, &inputs.httpContentFormat, nil); err != nil { return err } + if err := httpAuthorization.Ask(cmd, &inputs.HttpAuthorization, nil); err != nil { return err } - //if err := httpCustomHeaders.Ask(cmd, &inputs.HttpCustomHeaders, nil); err != nil { - // return err - //} + ls.Sink = &management.LogStreamSinkHTTP{ Authorization: &inputs.HttpAuthorization, ContentType: &inputs.HttpContentType, ContentFormat: &inputs.httpContentFormat, Endpoint: &inputs.HttpEndpoint, - //CustomHeaders: stringToInterfaceSlice(inputs.HttpCustomHeaders), } } @@ -322,15 +319,19 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := splunkDomain.Ask(cmd, &inputs.SplunkDomain, nil); err != nil { return err } + if err := splunkToken.Ask(cmd, &inputs.SplunkToken, nil); err != nil { return err } + if err := splunkPort.Ask(cmd, &inputs.SplunkPort, nil); err != nil { return err } + if err := splunkVerifyTLS.AskBool(cmd, &inputs.SplunkVerifyTLS, nil); err != nil { return err } + ls.Sink = &management.LogStreamSinkSplunk{ Domain: &inputs.SplunkDomain, Token: &inputs.SplunkToken, @@ -344,6 +345,7 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := sumoLogicSource.Ask(cmd, &inputs.SumoLogicSource, nil); err != nil { return err } + ls.Sink = &management.LogStreamSinkSumo{ SourceAddress: &inputs.SumoLogicSource, } @@ -354,9 +356,11 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := datadogApiKey.Ask(cmd, &inputs.DatadogAPIKey, nil); err != nil { return err } + if err := datadogRegion.Ask(cmd, &inputs.DatadogRegion, nil); err != nil { return err } + ls.Sink = &management.LogStreamSinkDatadog{ Region: &inputs.DatadogRegion, APIKey: &inputs.DatadogAPIKey, @@ -368,9 +372,11 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := awsAccountID.Ask(cmd, &inputs.AwsAccountID, nil); err != nil { return err } + if err := awsRegion.Ask(cmd, &inputs.AwsRegion, nil); err != nil { return err } + ls.Sink = &management.LogStreamSinkAmazonEventBridge{ AccountID: &inputs.AwsAccountID, Region: &inputs.AwsRegion, @@ -382,12 +388,15 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 if err := azureSubscriptionID.Ask(cmd, &inputs.AzureSubscriptionID, nil); err != nil { return err } + if err := azureRegion.Ask(cmd, &inputs.AzureRegion, nil); err != nil { return err } + if err := azureResourceGroup.Ask(cmd, &inputs.AzureResourceGroup, nil); err != nil { return err } + ls.Sink = &management.LogStreamSinkAzureEventGrid{ SubscriptionID: &inputs.AzureSubscriptionID, ResourceGroup: &inputs.AzureResourceGroup, @@ -414,7 +423,6 @@ auth0 logs streams create -n myeventbridge -t eventbridge --eventbridge-id 99999 httpContentType.RegisterString(cmd, &inputs.HttpContentType, "") httpContentFormat.RegisterString(cmd, &inputs.httpContentFormat, "") httpAuthorization.RegisterString(cmd, &inputs.HttpAuthorization, "") - httpCustomHeaders.RegisterStringSlice(cmd, &inputs.HttpCustomHeaders, nil) splunkDomain.RegisterString(cmd, &inputs.SplunkDomain, "") splunkToken.RegisterString(cmd, &inputs.SplunkToken, "") splunkPort.RegisterString(cmd, &inputs.SplunkPort, "") @@ -457,10 +465,10 @@ func updateLogStreamCmd(cli *cli) *cobra.Command { Long: "Update a new log stream.", Example: `auth0 logs streams update auth0 logs streams update --name mylogstream -auth0 logs streams update -n mylogstream --type http -auth0 logs streams update -n mylogstream -t http --http-type application/json --http-format JSONLINES -auth0 logs streams update -n mydatadog -t datadog --datadog-key 9999999 --datadog-id us -auth0 logs streams update -n myeventbridge -t eventbridge`, +auth0 logs streams update -n mylogstream --type http +auth0 logs streams update -n mylogstream -t http --http-type application/json --http-format JSONLINES +auth0 logs streams update -n mydatadog -t datadog --datadog-key 9999999 --datadog-id us +auth0 logs streams update -n myeventbridge -t eventbridge`, RunE: func(cmd *cobra.Command, args []string) error { var current *management.LogStream @@ -509,6 +517,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if err := datadogApiKey.AskU(cmd, &inputs.DatadogAPIKey, s.APIKey); err != nil { return err } + if err := datadogRegion.AskU(cmd, &inputs.DatadogRegion, s.Region); err != nil { return err } @@ -516,6 +525,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if len(inputs.DatadogAPIKey) > 0 { s.APIKey = &inputs.DatadogAPIKey } + if len(inputs.DatadogRegion) > 0 { s.Region = &inputs.DatadogRegion } @@ -534,6 +544,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if err := json.Unmarshal([]byte(res), s); err != nil { fmt.Println(err) } + if err := sumoLogicSource.AskU(cmd, &inputs.SumoLogicSource, s.SourceAddress); err != nil { return err } @@ -541,6 +552,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if len(inputs.SumoLogicSource) > 0 { s.SourceAddress = &inputs.SumoLogicSource } + ls.Sink = &management.LogStreamSinkSumo{ SourceAddress: s.SourceAddress, } @@ -558,12 +570,15 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if err := splunkDomain.AskU(cmd, &inputs.SplunkDomain, s.Domain); err != nil { return err } + if err := splunkToken.AskU(cmd, &inputs.SplunkToken, s.Token); err != nil { return err } + if err := splunkPort.AskU(cmd, &inputs.SplunkPort, s.Port); err != nil { return err } + if err := splunkVerifyTLS.AskBoolU(cmd, &inputs.SplunkVerifyTLS, s.Secure); err != nil { return err } @@ -571,12 +586,15 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if len(inputs.SplunkDomain) > 0 { s.Domain = &inputs.SplunkDomain } + if len(inputs.SplunkToken) > 0 { s.Token = &inputs.SplunkToken } + if len(inputs.SplunkPort) > 0 { s.Port = &inputs.SplunkPort } + if !splunkVerifyTLS.IsSet(cmd) { s.Secure = auth0.Bool(inputs.SplunkVerifyTLS) } @@ -597,15 +615,19 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if err := json.Unmarshal([]byte(res), s); err != nil { fmt.Println(err) } + if err := httpEndpoint.AskU(cmd, &inputs.HttpEndpoint, s.Endpoint); err != nil { return err } + if err := httpContentType.AskU(cmd, &inputs.HttpContentType, s.ContentType); err != nil { return err } + if err := httpContentFormat.AskU(cmd, &inputs.httpContentFormat, s.ContentFormat); err != nil { return err } + if err := httpAuthorization.AskU(cmd, &inputs.HttpAuthorization, s.Authorization); err != nil { return err } @@ -613,12 +635,15 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, if len(inputs.HttpEndpoint) > 0 { s.Endpoint = &inputs.HttpEndpoint } + if len(inputs.HttpContentType) > 0 { s.ContentType = &inputs.HttpContentType } + if len(inputs.httpContentFormat) > 0 { s.ContentFormat = &inputs.httpContentFormat } + if len(inputs.HttpAuthorization) > 0 { s.Authorization = &inputs.HttpAuthorization } From 0eb95c2f48379bedc76893d43a4b1964de915666 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Fri, 28 May 2021 09:25:29 -0400 Subject: [PATCH 06/11] [CLI-169] logs streams refactor: comments cleanup --- internal/cli/log_streams.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 72acee525..64b7d7318 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -461,8 +461,8 @@ func updateLogStreamCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "update", Args: cobra.MaximumNArgs(1), - Short: "Update a new log stream", - Long: "Update a new log stream.", + Short: "Update a log stream", + Long: "Update a log stream.", Example: `auth0 logs streams update auth0 logs streams update --name mylogstream auth0 logs streams update -n mylogstream --type http From a4b54be2207e3e34fef92311ab379208d03024c2 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Fri, 28 May 2021 09:42:57 -0400 Subject: [PATCH 07/11] [CLI-169] logs streams refactor: gofmt --- internal/cli/log_streams.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 64b7d7318..5918b8ae5 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -238,7 +238,7 @@ func createLogStreamCmd(cli *cli) *cobra.Command { Type string HttpEndpoint string HttpContentType string - httpContentFormat string + HttpContentFormat string HttpAuthorization string SplunkDomain string SplunkToken string @@ -298,7 +298,7 @@ auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.c return err } - if err := httpContentFormat.Ask(cmd, &inputs.httpContentFormat, nil); err != nil { + if err := httpContentFormat.Ask(cmd, &inputs.HttpContentFormat, nil); err != nil { return err } @@ -309,7 +309,7 @@ auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.c ls.Sink = &management.LogStreamSinkHTTP{ Authorization: &inputs.HttpAuthorization, ContentType: &inputs.HttpContentType, - ContentFormat: &inputs.httpContentFormat, + ContentFormat: &inputs.HttpContentFormat, Endpoint: &inputs.HttpEndpoint, } } @@ -421,7 +421,7 @@ auth0 logs streams create -n test-splunk -t splunk --splunk-domain demo.splunk.c logStreamType.RegisterString(cmd, &inputs.Type, "") httpEndpoint.RegisterString(cmd, &inputs.HttpEndpoint, "") httpContentType.RegisterString(cmd, &inputs.HttpContentType, "") - httpContentFormat.RegisterString(cmd, &inputs.httpContentFormat, "") + httpContentFormat.RegisterString(cmd, &inputs.HttpContentFormat, "") httpAuthorization.RegisterString(cmd, &inputs.HttpAuthorization, "") splunkDomain.RegisterString(cmd, &inputs.SplunkDomain, "") splunkToken.RegisterString(cmd, &inputs.SplunkToken, "") @@ -446,7 +446,7 @@ func updateLogStreamCmd(cli *cli) *cobra.Command { Type string HttpEndpoint string HttpContentType string - httpContentFormat string + HttpContentFormat string HttpAuthorization string HttpCustomHeaders []string SplunkDomain string @@ -624,7 +624,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, return err } - if err := httpContentFormat.AskU(cmd, &inputs.httpContentFormat, s.ContentFormat); err != nil { + if err := httpContentFormat.AskU(cmd, &inputs.HttpContentFormat, s.ContentFormat); err != nil { return err } @@ -640,8 +640,8 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, s.ContentType = &inputs.HttpContentType } - if len(inputs.httpContentFormat) > 0 { - s.ContentFormat = &inputs.httpContentFormat + if len(inputs.HttpContentFormat) > 0 { + s.ContentFormat = &inputs.HttpContentFormat } if len(inputs.HttpAuthorization) > 0 { @@ -679,7 +679,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, logStreamType.RegisterStringU(cmd, &inputs.Type, "") httpEndpoint.RegisterStringU(cmd, &inputs.HttpEndpoint, "") httpContentType.RegisterStringU(cmd, &inputs.HttpContentType, "") - httpContentFormat.RegisterStringU(cmd, &inputs.httpContentFormat, "") + httpContentFormat.RegisterStringU(cmd, &inputs.HttpContentFormat, "") httpAuthorization.RegisterStringU(cmd, &inputs.HttpAuthorization, "") splunkDomain.RegisterStringU(cmd, &inputs.SplunkDomain, "") splunkToken.RegisterStringU(cmd, &inputs.SplunkToken, "") From a9c586967f24ec5ab9fe9fb5ae24094c3eff026a Mon Sep 17 00:00:00 2001 From: bright-poku Date: Tue, 1 Jun 2021 20:04:00 -0400 Subject: [PATCH 08/11] [CLI-169] logs streams refactor: add suggestions --- internal/auth/auth_test.go | 1 + internal/cli/log_streams.go | 14 +++++++------- internal/display/log_streams.go | 4 ---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index 765bf706a..63600031b 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -6,6 +6,7 @@ func TestRequiredScopes(t *testing.T) { t.Run("verify CRUD", func(t *testing.T) { crudResources := []string{ "clients", + "log_streams", "resource_servers", "roles", "rules", diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 5918b8ae5..b204c4dcb 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -42,32 +42,32 @@ var ( } typeOptions = []string{ "Http", - "Eventbridge", - "Eventgrid", - "Datadog", + "EventBridge", + "EventGrid", + "DataDog", "Splunk", "Sumo", } httpEndpoint = Flag{ - Name: "Http Endpoint", + Name: "HTTP Endpoint", LongForm: "http-endpoint", Help: "HTTP endpoint.", IsRequired: true, } httpContentType = Flag{ - Name: "Http Content Type", + Name: "HTTP Content Type", LongForm: "http-type", Help: "HTTP Content-Type header. Possible values: application/json.", AlwaysPrompt: true, } httpContentFormat = Flag{ - Name: "Http Content Format", + Name: "HTTP Content Format", LongForm: "http-format", Help: "HTTP Content-Format header. Possible values: JSONLINES, JSONARRAY, JSONOBJECT.", AlwaysPrompt: true, } httpAuthorization = Flag{ - Name: "Http Authorization", + Name: "HTTP Authorization", LongForm: "http-auth", Help: "HTTP Authorization header.", AlwaysPrompt: true, diff --git a/internal/display/log_streams.go b/internal/display/log_streams.go index 65edba26c..9f3ad815a 100644 --- a/internal/display/log_streams.go +++ b/internal/display/log_streams.go @@ -10,7 +10,6 @@ type logStreamView struct { Name string Type string Status string - //Sink interface{} } func (v *logStreamView) AsTableHeader() []string { @@ -23,7 +22,6 @@ func (v *logStreamView) AsTableRow() []string { v.Name, v.Type, v.Status, - //fmt.Sprintln(v.Sink), } } @@ -33,7 +31,6 @@ func (v *logStreamView) KeyValues() [][]string { []string{"NAME", v.Name}, []string{"TYPE", v.Type}, []string{"STATUS", v.Status}, - //[]string{"SINK", fmt.Sprintln(v.Sink)}, } } @@ -82,6 +79,5 @@ func (r *Renderer) logStreamResult(logs *management.LogStream) { Name: logs.GetName(), Type: logs.GetType(), Status: logs.GetStatus(), - //Sink: logs.Sink, }) } From e614679dad862febff39dbce1f5d81e7c7cc5cae Mon Sep 17 00:00:00 2001 From: bright-poku Date: Tue, 1 Jun 2021 20:10:43 -0400 Subject: [PATCH 09/11] [CLI-169] format code --- internal/cli/log_streams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index b204c4dcb..73b542892 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -41,7 +41,7 @@ var ( IsRequired: true, } typeOptions = []string{ - "Http", + "HTTP", "EventBridge", "EventGrid", "DataDog", From 852b45262253f47be54f338d786a20432aa39e14 Mon Sep 17 00:00:00 2001 From: bright-poku Date: Tue, 1 Jun 2021 22:37:28 -0400 Subject: [PATCH 10/11] [CLI-169] add suggestions --- internal/cli/log_streams.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 73b542892..8255624a1 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -201,8 +201,8 @@ func showLogStreamCmd(cli *cli) *cobra.Command { cmd := &cobra.Command{ Use: "show", Args: cobra.MaximumNArgs(1), - Short: "Show a log stream by id", - Long: "Show an application.", + Short: "Show a log stream by Id", + Long: "Show a log stream by Id.", Example: `auth0 logs streams show auth0 logs streams show `, RunE: func(cmd *cobra.Command, args []string) error { @@ -222,7 +222,7 @@ auth0 logs streams show `, a, err = cli.api.LogStream.Read(inputs.ID) return err }); err != nil { - return fmt.Errorf("Unable to load application. The Id %v specified doesn't exist", inputs.ID) + return fmt.Errorf("Unable to load log stream. The Id %v specified doesn't exist", inputs.ID) } cli.renderer.LogStreamShow(a) return nil From bba9b1b248809292120af21c33131d9fbb3207fd Mon Sep 17 00:00:00 2001 From: bright-poku <75628344+bright-poku@users.noreply.github.com> Date: Wed, 2 Jun 2021 08:16:02 -0400 Subject: [PATCH 11/11] Update internal/cli/log_streams.go Co-authored-by: Rita Zerrizuela --- internal/cli/log_streams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/log_streams.go b/internal/cli/log_streams.go index 8255624a1..d0010be67 100644 --- a/internal/cli/log_streams.go +++ b/internal/cli/log_streams.go @@ -487,7 +487,7 @@ auth0 logs streams update -n myeventbridge -t eventbridge`, current, err = cli.api.LogStream.Read(inputs.ID) return err }); err != nil { - return fmt.Errorf("Unable to load logstreams. The Id %v specified doesn't exist", inputs.ID) + return fmt.Errorf("Unable to load logstream. The Id %v specified doesn't exist", inputs.ID) } // Prompt for log stream name