Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements generator cli for secrets #3531

Merged
merged 1 commit into from
Feb 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copyright head is incorrect.

// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package cmd

import (
"fmt"

"code.gitea.io/gitea/modules/generate"

"github.com/urfave/cli"
)

var (
// CmdGenerate represents the available generate sub-command.
CmdGenerate = cli.Command{
Name: "generate",
Usage: "Command line interface for running generators",
Subcommands: []cli.Command{
subcmdSecret,
},
}

subcmdSecret = cli.Command{
Name: "secret",
Usage: "Generate a secret token",
Subcommands: []cli.Command{
microcmdGenerateInternalToken,
microcmdGenerateLfsJwtSecret,
microcmdGenerateSecretKey,
},
}

microcmdGenerateInternalToken = cli.Command{
Name: "INTERNAL_TOKEN",
Usage: "Generate a new INTERNAL_TOKEN",
Action: runGenerateInternalToken,
}

microcmdGenerateLfsJwtSecret = cli.Command{
Name: "LFS_JWT_SECRET",
Usage: "Generate a new LFS_JWT_SECRET",
Action: runGenerateLfsJwtSecret,
}

microcmdGenerateSecretKey = cli.Command{
Name: "SECRET_KEY",
Usage: "Generate a new SECRET_KEY",
Action: runGenerateSecretKey,
}
)

func runGenerateInternalToken(c *cli.Context) error {
internalToken, err := generate.NewInternalToken()
if err != nil {
return err
}

fmt.Printf("%s\n", internalToken)
return nil
}

func runGenerateLfsJwtSecret(c *cli.Context) error {
JWTSecretBase64, err := generate.NewLfsJwtSecret()
if err != nil {
return err
}

fmt.Printf("%s\n", JWTSecretBase64)
return nil
}

func runGenerateSecretKey(c *cli.Context) error {
secretKey, err := generate.NewSecretKey()
if err != nil {
return err
}

fmt.Printf("%s\n", secretKey)
return nil
}
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ arguments - which can alternatively be run by running the subcommand web.`
cmd.CmdDump,
cmd.CmdCert,
cmd.CmdAdmin,
cmd.CmdGenerate,
}
app.Flags = append(app.Flags, []cli.Flag{}...)
app.Action = cmd.CmdWeb.Action
Expand Down
6 changes: 3 additions & 3 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
gouuid "github.com/satori/go.uuid"
"gopkg.in/ini.v1"

"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
Expand Down Expand Up @@ -539,10 +539,10 @@ func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
}

for _, org := range orgs {
if org.Rands, err = base.GetRandomString(10); err != nil {
if org.Rands, err = generate.GetRandomString(10); err != nil {
return err
}
if org.Salt, err = base.GetRandomString(10); err != nil {
if org.Salt, err = generate.GetRandomString(10); err != nil {
return err
}
if _, err = sess.Id(org.ID).Update(org); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions models/twofactor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

"github.com/pquerna/otp/totp"

"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
Expand All @@ -33,7 +33,7 @@ type TwoFactor struct {

// GenerateScratchToken recreates the scratch token the user is using.
func (t *TwoFactor) GenerateScratchToken() error {
token, err := base.GetRandomString(8)
token, err := generate.GetRandomString(8)
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (

"code.gitea.io/gitea/modules/avatar"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -638,7 +639,7 @@ func IsUserExist(uid int64, name string) (bool, error) {

// GetUserSalt returns a random user salt token.
func GetUserSalt() (string, error) {
return base.GetRandomString(10)
return generate.GetRandomString(10)
}

// NewGhostUser creates and returns a fake user for someone has deleted his/her account.
Expand Down
29 changes: 0 additions & 29 deletions modules/base/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"html/template"
"io"
"math"
"math/big"
"net/http"
"net/url"
"path"
Expand Down Expand Up @@ -88,25 +87,6 @@ func BasicAuthEncode(username, password string) string {
return base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
}

// GetRandomString generate random string by specify chars.
func GetRandomString(n int) (string, error) {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

buffer := make([]byte, n)
max := big.NewInt(int64(len(alphanum)))

for i := 0; i < n; i++ {
index, err := randomInt(max)
if err != nil {
return "", err
}

buffer[i] = alphanum[index]
}

return string(buffer), nil
}

// GetRandomBytesAsBase64 generates a random base64 string from n bytes
func GetRandomBytesAsBase64(n int) string {
bytes := make([]byte, 32)
Expand All @@ -119,15 +99,6 @@ func GetRandomBytesAsBase64(n int) string {
return base64.RawURLEncoding.EncodeToString(bytes)
}

func randomInt(max *big.Int) (int, error) {
rand, err := rand.Int(rand.Reader, max)
if err != nil {
return 0, err
}

return int(rand.Int64()), nil
}

// VerifyTimeLimitCode verify time limit code
func VerifyTimeLimitCode(data string, minutes int, code string) bool {
if len(code) <= 18 {
Expand Down
6 changes: 0 additions & 6 deletions modules/base/tool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,6 @@ func TestBasicAuthEncode(t *testing.T) {
assert.Equal(t, "Zm9vOmJhcg==", BasicAuthEncode("foo", "bar"))
}

func TestGetRandomString(t *testing.T) {
randomString, err := GetRandomString(4)
assert.NoError(t, err)
assert.Len(t, randomString, 4)
}

// TODO: Test PBKDF2()
// TODO: Test VerifyTimeLimitCode()
// TODO: Test CreateTimeLimitCode()
Expand Down
89 changes: 89 additions & 0 deletions modules/generate/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package generate

import (
"crypto/rand"
"encoding/base64"
"io"
"math/big"
"time"

"github.com/dgrijalva/jwt-go"
)

// GetRandomString generate random string by specify chars.
func GetRandomString(n int) (string, error) {
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

buffer := make([]byte, n)
max := big.NewInt(int64(len(alphanum)))

for i := 0; i < n; i++ {
index, err := randomInt(max)
if err != nil {
return "", err
}

buffer[i] = alphanum[index]
}

return string(buffer), nil
}

// NewInternalToken generate a new value intended to be used by INTERNAL_TOKEN.
func NewInternalToken() (string, error) {
secretBytes := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, secretBytes)
if err != nil {
return "", err
}

secretKey := base64.RawURLEncoding.EncodeToString(secretBytes)

now := time.Now()

var internalToken string
internalToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"nbf": now.Unix(),
}).SignedString([]byte(secretKey))
if err != nil {
return "", err
}

return internalToken, nil
}

// NewLfsJwtSecret generate a new value intended to be used by LFS_JWT_SECRET.
func NewLfsJwtSecret() (string, error) {
JWTSecretBytes := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, JWTSecretBytes)
if err != nil {
return "", err
}

JWTSecretBase64 := base64.RawURLEncoding.EncodeToString(JWTSecretBytes)
return JWTSecretBase64, nil
}

// NewSecretKey generate a new value intended to be used by SECRET_KEY.
func NewSecretKey() (string, error) {
secretKey, err := GetRandomString(64)
if err != nil {
return "", err
}

return secretKey, nil
}

func randomInt(max *big.Int) (int, error) {
rand, err := rand.Int(rand.Reader, max)
if err != nil {
return 0, err
}

return int(rand.Int64()), nil
}
20 changes: 20 additions & 0 deletions modules/generate/generate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package generate

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
retVal := m.Run()

os.Exit(retVal)
}

func TestGetRandomString(t *testing.T) {
randomString, err := GetRandomString(4)
assert.NoError(t, err)
assert.Len(t, randomString, 4)
}
28 changes: 5 additions & 23 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
package setting

import (
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"net"
"net/mail"
"net/url"
Expand All @@ -24,12 +22,12 @@ import (
"time"

"code.gitea.io/git"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
_ "code.gitea.io/gitea/modules/minwinsvc" // import minwinsvc for windows services
"code.gitea.io/gitea/modules/user"

"github.com/Unknwon/com"
"github.com/dgrijalva/jwt-go"
_ "github.com/go-macaron/cache/memcache" // memcache plugin for cache
_ "github.com/go-macaron/cache/redis"
"github.com/go-macaron/session"
Expand Down Expand Up @@ -834,16 +832,12 @@ func NewContext() {
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))

if err != nil || n != 32 {
//Generate new secret and save to config

_, err := io.ReadFull(rand.Reader, LFS.JWTSecretBytes)

LFS.JWTSecretBase64, err = generate.NewLfsJwtSecret()
if err != nil {
log.Fatal(4, "Error reading random bytes: %v", err)
log.Fatal(4, "Error generating JWT Secret for custom config: %v", err)
return
}

LFS.JWTSecretBase64 = base64.RawURLEncoding.EncodeToString(LFS.JWTSecretBytes)

// Save secret
cfg := ini.Empty()
if com.IsFile(CustomConf) {
Expand Down Expand Up @@ -913,19 +907,7 @@ func NewContext() {
DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(false)
InternalToken = sec.Key("INTERNAL_TOKEN").String()
if len(InternalToken) == 0 {
secretBytes := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, secretBytes)
if err != nil {
log.Fatal(4, "Error reading random bytes: %v", err)
}

secretKey := base64.RawURLEncoding.EncodeToString(secretBytes)

now := time.Now()
InternalToken, err = jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"nbf": now.Unix(),
}).SignedString([]byte(secretKey))

InternalToken, err = generate.NewInternalToken()
if err != nil {
log.Fatal(4, "Error generate internal token: %v", err)
}
Expand Down
Loading