forked from cesanta/docker_auth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request cesanta#55 from carsonoid/mongo_authn
Mongo authn
- Loading branch information
Showing
9 changed files
with
296 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
Copyright 2015 Cesanta Software Ltd. | ||
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 | ||
https://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. | ||
*/ | ||
|
||
package authn | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/cesanta/docker_auth/auth_server/mgo_session" | ||
"github.com/golang/glog" | ||
"golang.org/x/crypto/bcrypt" | ||
"gopkg.in/mgo.v2" | ||
"gopkg.in/mgo.v2/bson" | ||
) | ||
|
||
type MongoAuthConfig struct { | ||
MongoConfig *mgo_session.Config `yaml:"dial_info,omitempty"` | ||
Collection string `yaml:"collection,omitempty"` | ||
} | ||
|
||
type MongoAuth struct { | ||
config *MongoAuthConfig | ||
session *mgo.Session | ||
Collection string `yaml:"collection,omitempty"` | ||
} | ||
|
||
type authUserEntry struct { | ||
Username *string `yaml:"username,omitempty" json:"username,omitempty"` | ||
Password *string `yaml:"password,omitempty" json:"password,omitempty"` | ||
} | ||
|
||
func NewMongoAuth(c *MongoAuthConfig) (*MongoAuth, error) { | ||
// Attempt to create new mongo session. | ||
session, err := mgo_session.New(c.MongoConfig) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &MongoAuth{ | ||
config: c, | ||
session: session, | ||
}, nil | ||
} | ||
|
||
func (mauth *MongoAuth) Authenticate(account string, password PasswordString) (bool, error) { | ||
// Copy our session | ||
tmp_session := mauth.session.Copy() | ||
// Close up when we are done | ||
defer tmp_session.Close() | ||
|
||
// Get Users from MongoDB | ||
glog.V(2).Infof("Checking user %s against Mongo Users. DB: %s, collection:%s", | ||
account, mauth.config.MongoConfig.DialInfo.Database, mauth.config.Collection) | ||
var dbUserRecord authUserEntry | ||
collection := tmp_session.DB(mauth.config.MongoConfig.DialInfo.Database).C(mauth.config.Collection) | ||
err := collection.Find(bson.M{"username": account}).One(&dbUserRecord) | ||
|
||
// If we connect and get no results we return a NoMatch so auth can fall-through | ||
if err == mgo.ErrNotFound { | ||
return false, NoMatch | ||
} else if err != nil { | ||
return false, err | ||
} | ||
|
||
// Validate db password against passed password | ||
if dbUserRecord.Password != nil { | ||
if bcrypt.CompareHashAndPassword([]byte(*dbUserRecord.Password), []byte(password)) != nil { | ||
return false, nil | ||
} | ||
} | ||
|
||
// Auth success | ||
return true, nil | ||
} | ||
|
||
// Validate ensures that any custom config options | ||
// in a Config are set correctly. | ||
func (c *MongoAuthConfig) Validate(configKey string) error { | ||
//First validate the mongo config. | ||
if err := c.MongoConfig.Validate(configKey); err != nil { | ||
return err | ||
} | ||
|
||
// Now check additional config fields. | ||
if c.Collection == "" { | ||
return fmt.Errorf("%s.collection is required", configKey) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (ma *MongoAuth) Stop() { | ||
// Close connection to MongoDB database (if any) | ||
if ma.session != nil { | ||
ma.session.Close() | ||
} | ||
} | ||
|
||
func (ga *MongoAuth) Name() string { | ||
return "MongoDB" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
Copyright 2015 Cesanta Software Ltmc. | ||
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 | ||
https://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 impliemc. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package mgo_session | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"strings" | ||
"time" | ||
|
||
"github.com/golang/glog" | ||
"gopkg.in/mgo.v2" | ||
) | ||
|
||
// Config stores how to connect to the MongoDB server and an optional password file | ||
type Config struct { | ||
DialInfo mgo.DialInfo `yaml:",inline"` | ||
PasswordFile string `yaml:"password_file,omitempty"` | ||
} | ||
|
||
// Validate ensures the most common fields inside the mgo.DialInfo portion of | ||
// a Config are set correctly as well as other fields inside the | ||
// Config itself. | ||
func (c *Config) Validate(configKey string) error { | ||
if len(c.DialInfo.Addrs) == 0 { | ||
return fmt.Errorf("At least one element in %s.dial_info.addrs is required", configKey) | ||
} | ||
if c.DialInfo.Timeout == 0 { | ||
c.DialInfo.Timeout = 10 * time.Second | ||
} | ||
if c.DialInfo.Database == "" { | ||
return fmt.Errorf("%s.dial_info.database is required", configKey) | ||
} | ||
return nil | ||
} | ||
|
||
func New(c *Config) (*mgo.Session, error) { | ||
// Attempt to create a MongoDB session which we can re-use when handling | ||
// multiple requests. We can optionally read in the password from a file or directly from the config. | ||
|
||
// Read in the password (if any) | ||
if c.PasswordFile != "" { | ||
passBuf, err := ioutil.ReadFile(c.PasswordFile) | ||
if err != nil { | ||
return nil, fmt.Errorf(`Failed to read password file "%s": %s`, c.PasswordFile, err) | ||
} | ||
c.DialInfo.Password = strings.TrimSpace(string(passBuf)) | ||
} | ||
|
||
glog.V(2).Infof("Creating MongoDB session (operation timeout %s)", c.DialInfo.Timeout) | ||
|
||
session, err := mgo.DialWithInfo(&c.DialInfo) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return session, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.