From 17b2079f3e06b95ab1ad752ed1218795538a1606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zoran=20Peri=C4=8Di=C4=87?= Date: Wed, 12 Jan 2022 23:54:53 +0100 Subject: [PATCH] Add/update SMTP auth providers via cli (#18197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow adding/updating SMTP authentication source via CLI using: - gitea admin auth add-smtp - gitea admin auth update-smtp Signed-off-by: Zoran Peričić --- cmd/admin.go | 181 +++++++++++++++++++ docs/content/doc/usage/command-line.en-us.md | 27 +++ 2 files changed, 208 insertions(+) diff --git a/cmd/admin.go b/cmd/admin.go index ed2aa5de2..3c7f7c8a7 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/storage" auth_service "code.gitea.io/gitea/services/auth" "code.gitea.io/gitea/services/auth/source/oauth2" + "code.gitea.io/gitea/services/auth/source/smtp" repo_service "code.gitea.io/gitea/services/repository" user_service "code.gitea.io/gitea/services/user" @@ -190,6 +191,8 @@ var ( cmdAuthUpdateLdapBindDn, cmdAuthAddLdapSimpleAuth, cmdAuthUpdateLdapSimpleAuth, + microcmdAuthAddSMTP, + microcmdAuthUpdateSMTP, microcmdAuthList, microcmdAuthDelete, }, @@ -366,6 +369,72 @@ var ( }, }, } + + smtpCLIFlags = []cli.Flag{ + cli.StringFlag{ + Name: "name", + Value: "", + Usage: "Application Name", + }, + cli.StringFlag{ + Name: "auth-type", + Value: "PLAIN", + Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN", + }, + cli.StringFlag{ + Name: "host", + Value: "", + Usage: "SMTP Host", + }, + cli.IntFlag{ + Name: "port", + Usage: "SMTP Port", + }, + cli.BoolTFlag{ + Name: "force-smtps", + Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.", + }, + cli.BoolTFlag{ + Name: "skip-verify", + Usage: "Skip TLS verify.", + }, + cli.StringFlag{ + Name: "helo-hostname", + Value: "", + Usage: "Hostname sent with HELO. Leave blank to send current hostname", + }, + cli.BoolTFlag{ + Name: "disable-helo", + Usage: "Disable SMTP helo.", + }, + cli.StringFlag{ + Name: "allowed-domains", + Value: "", + Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')", + }, + cli.BoolTFlag{ + Name: "skip-local-2fa", + Usage: "Skip 2FA to log on.", + }, + cli.BoolTFlag{ + Name: "active", + Usage: "This Authentication Source is Activated.", + }, + } + + microcmdAuthAddSMTP = cli.Command{ + Name: "add-smtp", + Usage: "Add new SMTP authentication source", + Action: runAddSMTP, + Flags: smtpCLIFlags, + } + + microcmdAuthUpdateSMTP = cli.Command{ + Name: "update-smtp", + Usage: "Update existing SMTP authentication source", + Action: runUpdateSMTP, + Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...), + } ) func runChangePassword(c *cli.Context) error { @@ -804,6 +873,118 @@ func runUpdateOauth(c *cli.Context) error { return auth.UpdateSource(source) } +func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error { + if c.IsSet("auth-type") { + conf.Auth = c.String("auth-type") + validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"} + if !contains(validAuthTypes, strings.ToUpper(c.String("auth-type"))) { + return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5") + } + conf.Auth = c.String("auth-type") + } + if c.IsSet("host") { + conf.Host = c.String("host") + } + if c.IsSet("port") { + conf.Port = c.Int("port") + } + if c.IsSet("allowed-domains") { + conf.AllowedDomains = c.String("allowed-domains") + } + if c.IsSet("force-smtps") { + conf.ForceSMTPS = c.BoolT("force-smtps") + } + if c.IsSet("skip-verify") { + conf.SkipVerify = c.BoolT("skip-verify") + } + if c.IsSet("helo-hostname") { + conf.HeloHostname = c.String("helo-hostname") + } + if c.IsSet("disable-helo") { + conf.DisableHelo = c.BoolT("disable-helo") + } + if c.IsSet("skip-local-2fa") { + conf.SkipLocalTwoFA = c.BoolT("skip-local-2fa") + } + return nil +} + +func runAddSMTP(c *cli.Context) error { + ctx, cancel := installSignals() + defer cancel() + + if err := initDB(ctx); err != nil { + return err + } + + if !c.IsSet("name") || len(c.String("name")) == 0 { + return errors.New("name must be set") + } + if !c.IsSet("host") || len(c.String("host")) == 0 { + return errors.New("host must be set") + } + if !c.IsSet("port") { + return errors.New("port must be set") + } + var active = true + if c.IsSet("active") { + active = c.BoolT("active") + } + + var smtpConfig smtp.Source + if err := parseSMTPConfig(c, &smtpConfig); err != nil { + return err + } + + // If not set default to PLAIN + if len(smtpConfig.Auth) == 0 { + smtpConfig.Auth = "PLAIN" + } + + return auth.CreateSource(&auth.Source{ + Type: auth.SMTP, + Name: c.String("name"), + IsActive: active, + Cfg: &smtpConfig, + }) +} + +func runUpdateSMTP(c *cli.Context) error { + if !c.IsSet("id") { + return fmt.Errorf("--id flag is missing") + } + + ctx, cancel := installSignals() + defer cancel() + + if err := initDB(ctx); err != nil { + return err + } + + source, err := auth.GetSourceByID(c.Int64("id")) + if err != nil { + return err + } + + smtpConfig := source.Cfg.(*smtp.Source) + + if err := parseSMTPConfig(c, smtpConfig); err != nil { + return err + } + + if c.IsSet("name") { + source.Name = c.String("name") + } + + if c.IsSet("active") { + source.IsActive = c.BoolT("active") + } + + source.Cfg = smtpConfig + + return auth.UpdateSource(source) +} + func runListAuth(c *cli.Context) error { ctx, cancel := installSignals() defer cancel() diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index e477f31f1..90e872e63 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -161,6 +161,33 @@ Admin operations: - `--restricted-group`: Group Claim value for restricted users. (Optional) - Examples: - `gitea admin auth update-oauth --id 1 --name external-github-updated` + - `add-smtp`: + - Options: + - `--name`: Application Name. Required. + - `--auth-type`: SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5). Default to PLAIN. + - `--host`: SMTP host. Required. + - `--port`: SMTP port. Required. + - `--force-smtps`: SMTPS is always used on port 465. Set this to force SMTPS on other ports. + - `--skip-verify`: Skip TLS verify. + - `--helo-hostname`: Hostname sent with HELO. Leave blank to send current hostname. + - `--disable-helo`: Disable SMTP helo. + - `--allowed-domains`: Leave empty to allow all domains. Separate multiple domains with a comma (','). + - `--skip-local-2fa`: Skip 2FA to log on. + - `--active`: This Authentication Source is Activated. + Remarks: + `--force-smtps`, `--skip-verify`, `--disable-helo`, `--skip-loca-2fs` and `--active` options can be used in form: + - `--option`, `--option=true` to enable + - `--option=false` to disable + If those options are not specified value would not be changed in `update-smtp` or would use default `false` value in `add-smtp` + - Examples: + - `gitea admin auth add-smtp --name ldap --host smtp.mydomain.org --port 587 --skip-verify --active` + - `update-smtp`: + - Options: + - `--id`: ID of source to be updated. Required. + - other options are shared with `add-smtp` + - Examples: + - `gitea admin auth update-smtp --id 1 --host smtp.mydomain.org --port 587 --skip-verify=false` + - `gitea admin auth update-smtp --id 1 --active=false` - `add-ldap`: Add new LDAP (via Bind DN) authentication source - Options: - `--name value`: Authentication name. Required.