Skip to content
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
10 changes: 8 additions & 2 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,14 @@ func (s *server) createDatastore(ctx context.Context, cfg *config.ControlPlaneSp
options := []mongodb.Option{
mongodb.WithLogger(logger),
}
return mongodb.NewMongoDB(ctx, mdConfig.URL, mdConfig.Database, options...)

if mdConfig.UsernameFile != "" || mdConfig.PasswordFile != "" {
options = append(options, mongodb.WithAuthenticationFile(mdConfig.UsernameFile, mdConfig.PasswordFile))
}
return mongodb.NewMongoDB(
ctx,
mdConfig.URL,
mdConfig.Database,
options...)
Copy link
Member

Choose a reason for hiding this comment

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

nit: Just want to be unified with our coding conventions.

mongodb.NewMongoDB(
   ctx,
   mdConfig.URL,
   ...,
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nghialv
Thanks for your review.
I changed it to match the coding conventions. Please check it again when you have time 👍 👍

default:
return nil, fmt.Errorf("unknown datastore type %q", cfg.Datastore.Type)
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/app/ops/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,15 @@ func (s *server) createDatastore(ctx context.Context, cfg *config.ControlPlaneSp
options := []mongodb.Option{
mongodb.WithLogger(logger),
}
return mongodb.NewMongoDB(ctx, mdConfig.URL, mdConfig.Database, options...)

if mdConfig.UsernameFile != "" || mdConfig.PasswordFile != "" {
options = append(options, mongodb.WithAuthenticationFile(mdConfig.UsernameFile, mdConfig.PasswordFile))
}
return mongodb.NewMongoDB(
ctx,
mdConfig.URL,
mdConfig.Database,
options...,
)
default:
return nil, fmt.Errorf("unknown datastore type %q", cfg.Datastore.Type)
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/control_plane.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ type DataStoreMongoDBConfig struct {
// The url of MongoDB. All of credentials can be specified via this field.
URL string `json:"url"`
// The name of the database.
// Also set Database as 'AuthSource' (default as 'admin' or '$external') when UsernameFle || PasswordFile specify
// Ref: https://github.com/mongodb/mongo-go-driver/blob/9e2aca8afd8821e6b068cc2f25192bc640d90a0d/mongo/client.go#L390
Database string `json:"database"`
// The path to the username file.
// For those who don't want to include the username in the URL.
Expand Down
61 changes: 54 additions & 7 deletions pkg/datastore/mongodb/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package mongodb
import (
"context"
"errors"
"fmt"
"io/ioutil"
"strings"

"go.mongodb.org/mongo-driver/bson"
Expand All @@ -27,17 +29,23 @@ import (
"github.com/pipe-cd/pipe/pkg/datastore"
)

type MongoDB struct {
ctx context.Context
client *mongo.Client
database string
const (
// Scram type ref https://github.com/mongodb/mongo-go-driver/blob/9e2aca8afd8821e6b068cc2f25192bc640d90a0d/mongo/client_examples_test.go#L119
// Default
scram string = "SCRAM"
)

logger *zap.Logger
type MongoDB struct {
ctx context.Context
client *mongo.Client
database string
logger *zap.Logger
authMechanism string
usernameFile string
passwordFile string
}

func NewMongoDB(ctx context.Context, url, database string, opts ...Option) (*MongoDB, error) {
// TODO: Enable to specify username and password via file.
// Need to check if it overrides AuthMechanism etc.
m := &MongoDB{
ctx: ctx,
database: database,
Expand All @@ -49,6 +57,15 @@ func NewMongoDB(ctx context.Context, url, database string, opts ...Option) (*Mon
m.logger = m.logger.Named("mongodb")

clientOpts := options.Client().ApplyURI(url)

if m.authMechanism != "" {
credential, err := m.determineCredential()
if err != nil {
return nil, err
}
clientOpts.SetAuth(*credential)
}

client, err := mongo.Connect(ctx, clientOpts)
if err != nil {
return nil, err
Expand All @@ -59,6 +76,14 @@ func NewMongoDB(ctx context.Context, url, database string, opts ...Option) (*Mon

type Option func(*MongoDB)

func WithAuthenticationFile(usernameFile, passwordFile string) Option {
return func(m *MongoDB) {
m.usernameFile = usernameFile
m.passwordFile = passwordFile
m.authMechanism = scram
}
}

func WithLogger(logger *zap.Logger) Option {
return func(s *MongoDB) {
s.logger = logger
Expand Down Expand Up @@ -227,3 +252,25 @@ func (m *MongoDB) Close() error {
func makePrimaryKeyFilter(id string) bson.D {
return bson.D{{"_id", id}}
}

func (m *MongoDB) determineCredential() (*options.Credential, error) {
switch m.authMechanism {
case scram:
username, err := ioutil.ReadFile(m.usernameFile)
if err != nil {
return nil, fmt.Errorf("failed to read username file: %w", err)
}
password, err := ioutil.ReadFile(m.passwordFile)
if err != nil {
return nil, fmt.Errorf("failed to read password file: %w", err)
}

return &options.Credential{
Username: strings.TrimRight(string(username), "\n"),
Password: strings.TrimRight(string(password), "\n"),
AuthSource: m.database,
}, nil
default:
return nil, fmt.Errorf("unsupported %q authMechanism credential", m.authMechanism)
}
}