diff --git a/cmd/common-input.go b/cmd/common-input.go index 155566d..4222aa6 100644 --- a/cmd/common-input.go +++ b/cmd/common-input.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "os" "reflect" "strconv" @@ -91,6 +92,10 @@ func initInputFlags(cmd *cobra.Command, typeName string, fields ...inputField) { cmd.Flags().IntP(field.FlagName, field.FlagShorthand, field.DefaultValue.(int), field.FlagDescription) case "string": cmd.Flags().StringP(field.FlagName, field.FlagShorthand, field.DefaultValue.(string), field.FlagDescription) + case "string+file": + cmd.Flags().StringP(field.FlagName, field.FlagShorthand, field.DefaultValue.(string), field.FlagDescription) + // special case to read input from file, appends -file to argument + cmd.Flags().StringP(wrapFlagForFile(field.FlagName), field.FlagShorthand, field.DefaultValue.(string), field.FlagDescription+" (from file path)") case "[]int": // see https://github.com/spf13/pflag/issues/222 // cmd.Flags().IntSliceP(field.FlagName, field.FlagShorthand, field.DefaultValue.([]int), field.FlagDescription) @@ -144,12 +149,21 @@ func preRunFlagCheckInput(cmd *cobra.Command, args []string) error { return nil } -func getFlagValue(cmd *cobra.Command, varType, flagName string) (interface{}, error) { - if !cmd.Flags().Changed(flagName) { - return nil, fmt.Errorf("user did not specify %s", flagName) +func wrapFlagForFile(flagName string) string { + return flagName + "-file" +} + +func getFlagValueChanged(cmd *cobra.Command, varType, flagName string) bool { + changed := cmd.Flags().Changed(flagName) + if !changed && varType == "string+file" { + changed = cmd.Flags().Changed(wrapFlagForFile(flagName)) } - var value interface{} + return changed +} + +func getFlagValue(cmd *cobra.Command, varType, flagName string) (interface{}, error) { var err error + var value interface{} switch varType { case "bool": value, err = cmd.Flags().GetBool(flagName) @@ -157,6 +171,24 @@ func getFlagValue(cmd *cobra.Command, varType, flagName string) (interface{}, er value, err = cmd.Flags().GetInt(flagName) case "string": value, err = cmd.Flags().GetString(flagName) + case "string+file": + // If string value was passed, return it, otherwise, attempt to read from file + value, err = cmd.Flags().GetString(flagName) + if err != nil { + return nil, err + } + if value != "" { + return value, nil + } + filename, err := cmd.Flags().GetString(wrapFlagForFile(flagName)) + if err != nil { + return nil, err + } + contents, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + value = string(contents) case "[]int": // see https://github.com/spf13/pflag/issues/222 // we accepted a string slice instead, and will now convert to a int slice @@ -219,7 +251,8 @@ func forAllInput(cmd *cobra.Command, for i, field := range data.fields { var d interface{} - if !cmd.Flags().Changed(field.FlagName) && field.Mandatory { + flagChanged := getFlagValueChanged(cmd, field.VarType, field.FlagName) + if !flagChanged && field.Mandatory { // user did not supply the field value in a flag fieldInArgs := false if field.MainField { @@ -230,7 +263,7 @@ func forAllInput(cmd *cobra.Command, // must ask interactively d = interactivelyReadField(cmd, field) } - } else if !cmd.Flags().Changed(field.FlagName) && !writeDefaultValues { + } else if !flagChanged && !writeDefaultValues { // in placeInputValues, we only call the respective function for this field // if the value for the entry is not nil. so, we just leave it nil, to indicate this value is not provided continue diff --git a/cmd/root-settings.go b/cmd/root-settings.go index 0a4fd38..120add1 100644 --- a/cmd/root-settings.go +++ b/cmd/root-settings.go @@ -42,12 +42,18 @@ var settingsAnalyticsCmd = &cobra.Command{ Short: "Operations on analytics", } +var settingsIdentityProviderConfigCmd = &cobra.Command{ + Use: "idp", + Short: "Configure Identity Provider settings", +} + func init() { rootCmd.AddCommand(settingsCmd) settingsCmd.AddCommand(settingsAgentConfigCmd) settingsCmd.AddCommand(settingsEnrollmentCmd) settingsCmd.AddCommand(settingsAnalyticsCmd) + settingsCmd.AddCommand(settingsIdentityProviderConfigCmd) // Here you will define your flags and configuration settings. diff --git a/cmd/settings-idp-delete.go b/cmd/settings-idp-delete.go new file mode 100644 index 0000000..a1828c1 --- /dev/null +++ b/cmd/settings-idp-delete.go @@ -0,0 +1,105 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + "fmt" + + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + + "github.com/spf13/cobra" +) + +// deleteIdpCmd represents the get command +var deleteIdpCmd = &cobra.Command{ + Use: "delete [idp ID]...", + Aliases: []string{"remove", "rm"}, + Short: "Delete idps", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + if !multiOpCheckArgsPresent(cmd, args) { + return fmt.Errorf("missing idp ID argument") + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + adminIDs, err := multiOpParseInt64Args(cmd, args, "id") + if err != nil { + return err + } + + delete := func(ids []int64) error { + params := api.NewDeleteIdentityProviderParams() + setTenant(cmd, params) + params.SetID(ids) + + _, err = global.Client.IdentityProviders.DeleteIdentityProvider(params, global.AuthWriter) + if err != nil { + return processErrorResponse(err) + } + return nil + } + + tw, j := multiOpBuildTableWriter() + + if loopControlContinueOnError(cmd) { + // then we must delete individually, because on a request for multiple deletions, + // the server does nothing if one fails + + for _, id := range adminIDs { + err = delete([]int64{id}) + var result interface{} + result = "success" + if err != nil { + result = err + } + multiOpTableWriterAppend(tw, &j, id, result) + } + err = nil + } else { + err = delete(adminIDs) + var result interface{} + result = "success" + if err != nil { + result = err + } + multiOpTableWriterAppend(tw, &j, "*", result) + } + + return printListOutputAndError(cmd, j, tw, len(adminIDs), err) + }, +} + +func init() { + settingsIdentityProviderConfigCmd.AddCommand(deleteIdpCmd) + + initMultiOpArgFlags(deleteIdpCmd, "idp", "delete", "id", "[]int64") + initOutputFlags(deleteIdpCmd) + initLoopControlFlags(deleteIdpCmd) + initTenantFlags(deleteIdpCmd) +} diff --git a/cmd/settings-idp-get.go b/cmd/settings-idp-get.go new file mode 100644 index 0000000..fd8b09c --- /dev/null +++ b/cmd/settings-idp-get.go @@ -0,0 +1,139 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + "fmt" + "strconv" + + "github.com/jedib0t/go-pretty/v6/table" + "github.com/jedib0t/go-pretty/v6/text" + "github.com/spf13/cobra" + + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/barracuda-cloudgen-access/access-cli/models" +) + +// getIdentityProviderCmd represents the get command +var getIdentityProviderCmd = &cobra.Command{ + Use: "get [idp ID]", + Short: "Get IdP configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + if len(args) == 0 && !cmd.Flags().Changed("id") { + return fmt.Errorf("missing user ID argument") + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + var id int64 + var err error + if cmd.Flags().Changed("id") { + var d int + d, err = cmd.Flags().GetInt("id") + id = int64(d) + } else { + id, err = strconv.ParseInt(args[0], 10, 64) + } + if err != nil { + return err + } + + cmd.SilenceUsage = true // errors beyond this point are no longer due to malformed input + + params := api.NewGetIdentityProviderParams() + setTenant(cmd, params) + params.SetID(id) + + resp, err := global.Client.IdentityProviders.GetIdentityProvider(params, global.AuthWriter) + if err != nil { + return processErrorResponse(err) + } + + tw := identityProviderConfigBuildTableWriter() + if resp.Payload.IdentityProvider.ID > 0 { + identityProviderTableWriterAppend(tw, resp.Payload.IdentityProvider) + } + + return printListOutputAndError(cmd, resp.Payload, tw, 1, err) + }, +} + +func identityProviderConfigBuildTableWriter() table.Writer { + tw := table.NewWriter() + tw.Style().Format.Header = text.FormatDefault + tw.AppendHeader(table.Row{ + "ID", + "Type", + "Name", + "CreatedAt", + "UpdatedAt", + }) + + return tw +} + +func identityProviderTableWriterAppend(tw table.Writer, idp models.IdentityProvider) table.Writer { + tw.AppendRow(table.Row{ + idp.ID, + idp.IdpType, + idp.Name, + idp.CreatedAt, + idp.UpdatedAt, + }) + return tw +} + +func identityProviderTableWriterAppendError(tw table.Writer, err error, id interface{}) { + tw.AppendRow(table.Row{ + "[ERR]", + processErrorResponse(err), + "-", + "-", + "-", + }) +} + +func init() { + settingsIdentityProviderConfigCmd.AddCommand(getIdentityProviderCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // getIdentityProviderCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // getIdentityProviderCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + + initOutputFlags(getIdentityProviderCmd) + initTenantFlags(getIdentityProviderCmd) + + getIdentityProviderCmd.Flags().Int("id", 0, "id of user to get") +} diff --git a/cmd/settings-idp-list.go b/cmd/settings-idp-list.go new file mode 100644 index 0000000..05d46ba --- /dev/null +++ b/cmd/settings-idp-list.go @@ -0,0 +1,77 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + "github.com/spf13/cobra" + + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" +) + +// listIdentityProviderCmd represents the get command +var listIdentityProviderCmd = &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "List IdP configurations", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + params := api.NewListIdentityProviderParams() + setTenant(cmd, params) + + resp, err := global.Client.IdentityProviders.ListIdentityProvider(params, global.AuthWriter) + if err != nil { + return processErrorResponse(err) + } + + tw := identityProviderConfigBuildTableWriter() + if resp.Payload.ID > 0 { + identityProviderTableWriterAppend(tw, *resp.Payload) + } + + return printListOutputAndError(cmd, resp.Payload, tw, 1, err) + }, +} + +func init() { + settingsIdentityProviderConfigCmd.AddCommand(listIdentityProviderCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // listIdentityProviderCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // listIdentityProviderCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + + initOutputFlags(listIdentityProviderCmd) + initTenantFlags(listIdentityProviderCmd) +} diff --git a/cmd/settings-idp-set-barracuda.go b/cmd/settings-idp-set-barracuda.go new file mode 100644 index 0000000..4210462 --- /dev/null +++ b/cmd/settings-idp-set-barracuda.go @@ -0,0 +1,72 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/spf13/cobra" +) + +// setBarracudaIdpCmd represents the get command +var setBarracudaIdpCmd = &cobra.Command{ + Use: "barracuda", + Short: "Set barracuda idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + params := api.NewCreateIdentityProviderParams() + setTenant(cmd, params) + + cmd.SilenceUsage = true // errors beyond this point are no longer due to malformed input + + body := api.CreateIdentityProviderBody{ + IdentityProvider: &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "barracuda_oidc", + }} + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return err + } + + tw := identityProviderConfigBuildTableWriter() + if resp.Payload.ID > 0 { + identityProviderTableWriterAppend(tw, *resp.Payload) + } + return printListOutputAndError(cmd, resp.Payload, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setBarracudaIdpCmd) + + initOutputFlags(setBarracudaIdpCmd) + initTenantFlags(setBarracudaIdpCmd) +} diff --git a/cmd/settings-idp-set-email.go b/cmd/settings-idp-set-email.go new file mode 100644 index 0000000..b0e2de3 --- /dev/null +++ b/cmd/settings-idp-set-email.go @@ -0,0 +1,72 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/spf13/cobra" +) + +// setEmailIdpCmd represents the get command +var setEmailIdpCmd = &cobra.Command{ + Use: "email", + Short: "Set email idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + params := api.NewCreateIdentityProviderParams() + setTenant(cmd, params) + + cmd.SilenceUsage = true // errors beyond this point are no longer due to malformed input + + body := api.CreateIdentityProviderBody{ + IdentityProvider: &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "email", + }} + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return err + } + + tw := identityProviderConfigBuildTableWriter() + if resp.Payload.ID > 0 { + identityProviderTableWriterAppend(tw, *resp.Payload) + } + return printListOutputAndError(cmd, resp.Payload, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setEmailIdpCmd) + + initOutputFlags(setEmailIdpCmd) + initTenantFlags(setEmailIdpCmd) +} diff --git a/cmd/settings-idp-set-oidc-google.go b/cmd/settings-idp-set-oidc-google.go new file mode 100644 index 0000000..07e404b --- /dev/null +++ b/cmd/settings-idp-set-oidc-google.go @@ -0,0 +1,72 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/spf13/cobra" +) + +// setGoogleIdpCmd represents the get command +var setGoogleIdpCmd = &cobra.Command{ + Use: "google", + Short: "Set google idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + params := api.NewCreateIdentityProviderParams() + setTenant(cmd, params) + + cmd.SilenceUsage = true // errors beyond this point are no longer due to malformed input + + body := api.CreateIdentityProviderBody{ + IdentityProvider: &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "google_oidc", + }} + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return err + } + + tw := identityProviderConfigBuildTableWriter() + if resp.Payload.ID > 0 { + identityProviderTableWriterAppend(tw, *resp.Payload) + } + return printListOutputAndError(cmd, resp.Payload, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setGoogleIdpCmd) + + initOutputFlags(setGoogleIdpCmd) + initTenantFlags(setGoogleIdpCmd) +} diff --git a/cmd/settings-idp-set-oidc-microsoft.go b/cmd/settings-idp-set-oidc-microsoft.go new file mode 100644 index 0000000..3a2c3a7 --- /dev/null +++ b/cmd/settings-idp-set-oidc-microsoft.go @@ -0,0 +1,108 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/barracuda-cloudgen-access/access-cli/models" + "github.com/spf13/cobra" +) + +// setMicrosoftIdpCmd represents the get command +var setMicrosoftIdpCmd = &cobra.Command{ + Use: "microsoft", + Short: "Set microsoft idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + tw := identityProviderConfigBuildTableWriter() + createdList := []*models.IdentityProvider{} + total := 0 + + err := forAllInput(cmd, args, true, + func(values *inputEntry) (interface{}, error) { // do func + total++ // this is the total of successful+failures, must increment before failure + params := api.NewCreateIdentityProviderParams() + + idp := &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "azure_oidc", + Details: map[string]interface{}{}, + } + + err := placeInputValues(cmd, values, idp, + func(s []string) { idp.Details["issuer"] = s }) + if err != nil { + return nil, err + } + + setTenant(cmd, params) + + body := api.CreateIdentityProviderBody{ + IdentityProvider: idp, + } + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return nil, err + } + + return resp.Payload, nil + }, func(data interface{}) { // printSuccess func + idp := data.(*models.IdentityProvider) + if idp.ID > 0 { + identityProviderTableWriterAppend(tw, *idp) + } + createdList = append(createdList, idp) + }, func(err error, id interface{}) { // doOnError func + createdList = append(createdList, nil) + identityProviderTableWriterAppendError(tw, err, id) + }) + + return printListOutputAndError(cmd, createdList, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setMicrosoftIdpCmd) + + initOutputFlags(setMicrosoftIdpCmd) + initLoopControlFlags(setMicrosoftIdpCmd) + initTenantFlags(setMicrosoftIdpCmd) + + initInputFlags(setMicrosoftIdpCmd, "idp", + inputField{ + Name: "Allowed Azure ADs", + FlagName: "allowed-azure-ads", + FlagDescription: "List of allowed Azure Active Directory IDs", + VarType: "[]string", + Mandatory: true, + DefaultValue: []string{}, + }) +} diff --git a/cmd/settings-idp-set-oidc.go b/cmd/settings-idp-set-oidc.go new file mode 100644 index 0000000..81ce798 --- /dev/null +++ b/cmd/settings-idp-set-oidc.go @@ -0,0 +1,135 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/barracuda-cloudgen-access/access-cli/models" + "github.com/spf13/cobra" +) + +// setOidcIdpCmd represents the get command +var setOidcIdpCmd = &cobra.Command{ + Use: "oidc", + Short: "Set custom OIDC idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + tw := identityProviderConfigBuildTableWriter() + createdList := []*models.IdentityProvider{} + total := 0 + + err := forAllInput(cmd, args, true, + func(values *inputEntry) (interface{}, error) { // do func + total++ // this is the total of successful+failures, must increment before failure + params := api.NewCreateIdentityProviderParams() + + idp := &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "oidc", + Details: map[string]interface{}{}, + } + + err := placeInputValues(cmd, values, idp, + func(s string) { idp.Details["client_id"] = s }, + func(s string) { idp.Details["client_secret"] = s }, + func(s []string) { idp.Details["email_claims"] = s }, + func(s []string) { idp.Details["issuer"] = s }) + if err != nil { + return nil, err + } + + setTenant(cmd, params) + + body := api.CreateIdentityProviderBody{ + IdentityProvider: idp, + } + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return nil, err + } + + return resp.Payload, nil + }, func(data interface{}) { // printSuccess func + idp := data.(*models.IdentityProvider) + if idp.ID > 0 { + identityProviderTableWriterAppend(tw, *idp) + } + createdList = append(createdList, idp) + }, func(err error, id interface{}) { // doOnError func + createdList = append(createdList, nil) + identityProviderTableWriterAppendError(tw, err, id) + }) + + return printListOutputAndError(cmd, createdList, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setOidcIdpCmd) + + initOutputFlags(setOidcIdpCmd) + initLoopControlFlags(setOidcIdpCmd) + initTenantFlags(setOidcIdpCmd) + + initInputFlags(setOidcIdpCmd, "idp", + inputField{ + Name: "Client ID", + FlagName: "client-id", + FlagDescription: "Client ID for custom OIDC", + VarType: "string", + Mandatory: true, + DefaultValue: "", + }, + inputField{ + Name: "Client Secret", + FlagName: "client-secret", + FlagDescription: "Client Secret for custom OIDC", + VarType: "string", + Mandatory: true, + DefaultValue: "", + }, + inputField{ + Name: "Email Claims", + FlagName: "email-claims", + FlagDescription: "List of email claims", + VarType: "[]string", + Mandatory: true, + DefaultValue: []string{}, + }, + inputField{ + Name: "Allowed Issuers", + FlagName: "allowed-issuers", + FlagDescription: "List of allowed issuers", + VarType: "[]string", + Mandatory: true, + DefaultValue: []string{}, + }) +} diff --git a/cmd/settings-idp-set-root.go b/cmd/settings-idp-set-root.go new file mode 100644 index 0000000..43d2f2e --- /dev/null +++ b/cmd/settings-idp-set-root.go @@ -0,0 +1,32 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + "github.com/spf13/cobra" +) + +// setIdpCmd represents the settings command +var setIdpCmd = &cobra.Command{ + Use: "set", + Short: "Set idp configuration", +} + +func init() { + settingsIdentityProviderConfigCmd.AddCommand(setIdpCmd) +} diff --git a/cmd/settings-idp-set-saml.go b/cmd/settings-idp-set-saml.go new file mode 100644 index 0000000..5cc427a --- /dev/null +++ b/cmd/settings-idp-set-saml.go @@ -0,0 +1,126 @@ +// Package cmd implements access-cli commands +package cmd + +/* +Copyright © 2020 Barracuda Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import ( + api "github.com/barracuda-cloudgen-access/access-cli/client/identity_providers" + "github.com/barracuda-cloudgen-access/access-cli/models" + "github.com/spf13/cobra" +) + +// setSamlIdpCmd represents the get command +var setSamlIdpCmd = &cobra.Command{ + Use: "saml", + Short: "Set SAML idp configuration", + PreRunE: func(cmd *cobra.Command, args []string) error { + err := preRunCheckAuth(cmd, args) + if err != nil { + return err + } + + err = preRunFlagChecks(cmd, args) + if err != nil { + return err + } + + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + tw := identityProviderConfigBuildTableWriter() + createdList := []*models.IdentityProvider{} + total := 0 + + err := forAllInput(cmd, args, true, + func(values *inputEntry) (interface{}, error) { // do func + total++ // this is the total of successful+failures, must increment before failure + params := api.NewCreateIdentityProviderParams() + + idp := &api.CreateIdentityProviderParamsBodyIdentityProvider{ + IdpType: "saml", + Details: map[string]interface{}{}, + } + + err := placeInputValues(cmd, values, idp, + func(s string) { idp.Details["entity_id"] = s }, + func(s string) { idp.Details["sso_url"] = s }, + func(s string) { idp.Details["certificate"] = s }) + if err != nil { + return nil, err + } + + setTenant(cmd, params) + + body := api.CreateIdentityProviderBody{ + IdentityProvider: idp, + } + params.SetIdentityProvider(body) + + resp, err := global.Client.IdentityProviders.CreateIdentityProvider(params, global.AuthWriter) + if err != nil { + return nil, err + } + + return resp.Payload, nil + }, func(data interface{}) { // printSuccess func + idp := data.(*models.IdentityProvider) + if idp.ID > 0 { + identityProviderTableWriterAppend(tw, *idp) + } + createdList = append(createdList, idp) + }, func(err error, id interface{}) { // doOnError func + createdList = append(createdList, nil) + identityProviderTableWriterAppendError(tw, err, id) + }) + + return printListOutputAndError(cmd, createdList, tw, 1, err) + }, +} + +func init() { + setIdpCmd.AddCommand(setSamlIdpCmd) + + initOutputFlags(setSamlIdpCmd) + initLoopControlFlags(setSamlIdpCmd) + initTenantFlags(setSamlIdpCmd) + + initInputFlags(setSamlIdpCmd, "idp", + inputField{ + Name: "Entity ID", + FlagName: "entity_id", + FlagDescription: "SAML SSO Entity ID", + VarType: "string", + Mandatory: true, + DefaultValue: "", + }, + inputField{ + Name: "SSO URL", + FlagName: "sso_url", + FlagDescription: "SAML SSO Redirect URL", + VarType: "string", + Mandatory: true, + DefaultValue: "", + }, + inputField{ + Name: "Certificate", + FlagName: "certificate", + FlagDescription: "Certificate of the SAML provider", + VarType: "string+file", + Mandatory: true, + DefaultValue: "", + }) +} diff --git a/swagger.yml b/swagger.yml index dde1bd4..9c56cbd 100644 --- a/swagger.yml +++ b/swagger.yml @@ -2494,6 +2494,118 @@ paths: $ref: "#/responses/NotFound" 422: $ref: "#/responses/UnprocessableEntity" + + /tenants/{tenant_id}/identity_providers: + get: + tags: + - "identity_providers" + summary: "List identity provider" + operationId: "listIdentityProvider" + produces: + - "application/json" + parameters: + - $ref: '#/parameters/tenantIdParam' + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/IdentityProvider" + 401: + $ref: "#/responses/Unauthorized" + 404: + $ref: "#/responses/NotFound" + post: + tags: + - identity_providers + produces: + - "application/json" + consumes: + - "application/json" + summary: "Create identity provider" + operationId: "createIdentityProvider" + parameters: + - in: "body" + name: "identity_provider" + description: "Information about the identity provider to configure" + required: true + schema: + type: object + properties: + identity_provider: + type: object + properties: + idp_type: + type: string + enum: ["email", "oidc", "azure_oidc", "google_oidc", "barracuda_oidc", "saml"] + details: + type: object + additionalProperties: + type: object + description: IdP specific settings + - $ref: '#/parameters/tenantIdParam' + responses: + 201: + description: "successful operation" + schema: + $ref: "#/definitions/IdentityProvider" + 401: + $ref: "#/responses/Unauthorized" + 404: + $ref: "#/responses/NotFound" + 422: + $ref: "#/responses/UnprocessableEntity" + /tenants/{tenant_id}/identity_providers/{id}: + get: + tags: + - identity_providers + produces: + - "application/json" + summary: "Retrieve information about an identity provider" + operationId: "getIdentityProvider" + parameters: + - in: path + name: "id" + required: true + type: integer + description: "The ID of the IdP to retrieve" + - $ref: '#/parameters/tenantIdParam' + responses: + 200: + description: "Idp info" + schema: + allOf: + - $ref: "#/definitions/IdentityProvider" + 401: + $ref: "#/responses/Unauthorized" + 403: + $ref: "#/responses/Forbidden" + 404: + $ref: "#/responses/NotFound" + delete: + tags: + - identity_providers + summary: "Delete identity provider" + operationId: "deleteIdentityProvider" + parameters: + - in: path + name: "id" + required: true + type: array + collectionFormat: csv + items: + type: integer + description: "The IDs of the users to delete, comma-separated" + - $ref: '#/parameters/tenantIdParam' + responses: + 204: + description: "IdP deleted" + 401: + $ref: "#/responses/Unauthorized" + 404: + $ref: "#/responses/NotFound" + 422: + $ref: "#/responses/UnprocessableEntity" + /tenants: get: tags: @@ -3330,6 +3442,27 @@ definitions: type: string example: events.acme.org/post + IdentityProvider: + type: object + properties: + created_at: + type: string + format: date-time + details: + type: object + description: IdP specific settings + id: + type: integer + idp_type: + type: string + enum: ["email", "oidc", "azure_oidc", "google_oidc", "barracuda_oidc", "saml"] + name: + type: string + x-nullable: true + updated_at: + type: string + format: date-time + Tenant: type: object properties: