supabase-cli/cmd/sso.go

180 lines
8.2 KiB
Go

package cmd
import (
"github.com/go-errors/errors"
"github.com/spf13/cobra"
"github.com/supabase/cli/internal/sso/create"
"github.com/supabase/cli/internal/sso/get"
"github.com/supabase/cli/internal/sso/info"
"github.com/supabase/cli/internal/sso/list"
"github.com/supabase/cli/internal/sso/remove"
"github.com/supabase/cli/internal/sso/update"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
)
var (
ssoCmd = &cobra.Command{
GroupID: groupManagementAPI,
Use: "sso",
Short: "Manage Single Sign-On (SSO) authentication for projects",
}
ssoProviderType = utils.EnumFlag{
Allowed: []string{"saml"},
// intentionally no default value so users have to specify --type saml explicitly
}
ssoMetadataFile string
ssoMetadataURL string
ssoSkipURLValidation bool
ssoMetadata bool
ssoAttributeMappingFile string
ssoDomains []string
ssoAddDomains []string
ssoRemoveDomains []string
ssoAddCmd = &cobra.Command{
Use: "add",
Short: "Add a new SSO identity provider",
Long: "Add and configure a new connection to a SSO identity provider to your Supabase project.",
Example: ` supabase sso add --type saml --project-ref mwjylndxudmiehsxhmmz --metadata-url 'https://...' --domains example.com`,
RunE: func(cmd *cobra.Command, args []string) error {
return create.Run(cmd.Context(), create.RunParams{
ProjectRef: flags.ProjectRef,
Type: ssoProviderType.String(),
Format: utils.OutputFormat.Value,
MetadataFile: ssoMetadataFile,
MetadataURL: ssoMetadataURL,
SkipURLValidation: ssoSkipURLValidation,
AttributeMapping: ssoAttributeMappingFile,
Domains: ssoDomains,
})
},
}
ssoRemoveCmd = &cobra.Command{
Use: "remove <provider-id>",
Short: "Remove an existing SSO identity provider",
Long: "Remove a connection to an already added SSO identity provider. Removing the provider will prevent existing users from logging in. Please treat this command with care.",
Args: cobra.ExactArgs(1),
Example: ` supabase sso remove b5ae62f9-ef1d-4f11-a02b-731c8bbb11e8 --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
if !utils.UUIDPattern.MatchString(args[0]) {
return errors.Errorf("identity provider ID %q is not a UUID", args[0])
}
return remove.Run(cmd.Context(), flags.ProjectRef, args[0], utils.OutputFormat.Value)
},
}
ssoUpdateCmd = &cobra.Command{
Use: "update <provider-id>",
Short: "Update information about an SSO identity provider",
Long: "Update the configuration settings of a already added SSO identity provider.",
Args: cobra.ExactArgs(1),
Example: ` supabase sso update b5ae62f9-ef1d-4f11-a02b-731c8bbb11e8 --project-ref mwjylndxudmiehsxhmmz --add-domains example.com`,
RunE: func(cmd *cobra.Command, args []string) error {
if !utils.UUIDPattern.MatchString(args[0]) {
return errors.Errorf("identity provider ID %q is not a UUID", args[0])
}
return update.Run(cmd.Context(), update.RunParams{
ProjectRef: flags.ProjectRef,
ProviderID: args[0],
Format: utils.OutputFormat.Value,
MetadataFile: ssoMetadataFile,
MetadataURL: ssoMetadataURL,
SkipURLValidation: ssoSkipURLValidation,
AttributeMapping: ssoAttributeMappingFile,
Domains: ssoDomains,
AddDomains: ssoAddDomains,
RemoveDomains: ssoRemoveDomains,
})
},
}
ssoShowCmd = &cobra.Command{
Use: "show <provider-id>",
Short: "Show information about an SSO identity provider",
Long: "Provides the information about an established connection to an identity provider. You can use --metadata to obtain the raw SAML 2.0 Metadata XML document stored in your project's configuration.",
Args: cobra.ExactArgs(1),
Example: ` supabase sso show b5ae62f9-ef1d-4f11-a02b-731c8bbb11e8 --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
if !utils.UUIDPattern.MatchString(args[0]) {
return errors.Errorf("identity provider ID %q is not a UUID", args[0])
}
format := utils.OutputFormat.Value
if ssoMetadata {
format = utils.OutputMetadata
}
return get.Run(cmd.Context(), flags.ProjectRef, args[0], format)
},
}
ssoListCmd = &cobra.Command{
Use: "list",
Short: "List all SSO identity providers for a project",
Long: "List all connections to a SSO identity provider to your Supabase project.",
Example: ` supabase sso list --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
return list.Run(cmd.Context(), flags.ProjectRef, utils.OutputFormat.Value)
},
}
ssoInfoCmd = &cobra.Command{
Use: "info",
Short: "Returns the SAML SSO settings required for the identity provider",
Long: "Returns all of the important SSO information necessary for your project to be registered with a SAML 2.0 compatible identity provider.",
Example: ` supabase sso info --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
return info.Run(cmd.Context(), flags.ProjectRef, utils.OutputFormat.Value)
},
}
)
func init() {
persistentFlags := ssoCmd.PersistentFlags()
persistentFlags.StringVar(&flags.ProjectRef, "project-ref", "", "Project ref of the Supabase project.")
ssoAddFlags := ssoAddCmd.Flags()
ssoAddFlags.VarP(&ssoProviderType, "type", "t", "Type of identity provider (according to supported protocol).")
ssoAddFlags.StringSliceVar(&ssoDomains, "domains", nil, "Comma separated list of email domains to associate with the added identity provider.")
ssoAddFlags.StringVar(&ssoMetadataFile, "metadata-file", "", "File containing a SAML 2.0 Metadata XML document describing the identity provider.")
ssoAddFlags.StringVar(&ssoMetadataURL, "metadata-url", "", "URL pointing to a SAML 2.0 Metadata XML document describing the identity provider.")
ssoAddFlags.BoolVar(&ssoSkipURLValidation, "skip-url-validation", false, "Whether local validation of the SAML 2.0 Metadata URL should not be performed.")
ssoAddFlags.StringVar(&ssoAttributeMappingFile, "attribute-mapping-file", "", "File containing a JSON mapping between SAML attributes to custom JWT claims.")
ssoAddCmd.MarkFlagsMutuallyExclusive("metadata-file", "metadata-url")
cobra.CheckErr(ssoAddCmd.MarkFlagRequired("type"))
cobra.CheckErr(ssoAddCmd.MarkFlagFilename("metadata-file", "xml"))
cobra.CheckErr(ssoAddCmd.MarkFlagFilename("attribute-mapping-file", "json"))
ssoUpdateFlags := ssoUpdateCmd.Flags()
ssoUpdateFlags.StringSliceVar(&ssoDomains, "domains", []string{}, "Replace domains with this comma separated list of email domains.")
ssoUpdateFlags.StringSliceVar(&ssoAddDomains, "add-domains", []string{}, "Add this comma separated list of email domains to the identity provider.")
ssoUpdateFlags.StringSliceVar(&ssoRemoveDomains, "remove-domains", []string{}, "Remove this comma separated list of email domains from the identity provider.")
ssoUpdateFlags.StringVar(&ssoMetadataFile, "metadata-file", "", "File containing a SAML 2.0 Metadata XML document describing the identity provider.")
ssoUpdateFlags.StringVar(&ssoMetadataURL, "metadata-url", "", "URL pointing to a SAML 2.0 Metadata XML document describing the identity provider.")
ssoUpdateFlags.BoolVar(&ssoSkipURLValidation, "skip-url-validation", false, "Whether local validation of the SAML 2.0 Metadata URL should not be performed.")
ssoUpdateFlags.StringVar(&ssoAttributeMappingFile, "attribute-mapping-file", "", "File containing a JSON mapping between SAML attributes to custom JWT claims.")
ssoUpdateCmd.MarkFlagsMutuallyExclusive("metadata-file", "metadata-url")
ssoUpdateCmd.MarkFlagsMutuallyExclusive("domains", "add-domains")
ssoUpdateCmd.MarkFlagsMutuallyExclusive("domains", "remove-domains")
cobra.CheckErr(ssoUpdateCmd.MarkFlagFilename("metadata-file", "xml"))
cobra.CheckErr(ssoUpdateCmd.MarkFlagFilename("attribute-mapping-file", "json"))
ssoShowFlags := ssoShowCmd.Flags()
ssoShowFlags.BoolVar(&ssoMetadata, "metadata", false, "Show SAML 2.0 XML Metadata only")
ssoCmd.AddCommand(ssoAddCmd)
ssoCmd.AddCommand(ssoRemoveCmd)
ssoCmd.AddCommand(ssoUpdateCmd)
ssoCmd.AddCommand(ssoShowCmd)
ssoCmd.AddCommand(ssoListCmd)
ssoCmd.AddCommand(ssoInfoCmd)
rootCmd.AddCommand(ssoCmd)
}