8000 MF-1317 - Configurable regexp rule for password by blokovi · Pull Request #1355 · absmach/supermq · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MF-1317 - Configurable regexp rule for password #1355

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

Merged
merged 18 commits into from
Mar 1, 2021
Merged

Conversation

blokovi
Copy link
Contributor
@blokovi blokovi commented Feb 4, 2021

Signed-off-by: Ivan Milosevic iva@blokovi.com

Which issue(s) does this PR fix/relate to?

Resolves #1317

List any changes that modify/break current functionality

Have you included tests for your changes?

Did you document any new/modified functionality?

Notes

@manuio manuio mentioned this pull request Feb 8, 2021
@blokovi blokovi marked this pull request as ready for review February 12, 2021 11:41
@blokovi blokovi requested a review from a team as a code owner February 12, 2021 11:41
Comment on lines -75 to -81
"validate user with empty password": {
user: users.User{
Email: email,
Password: "",
},
err: users.ErrMalformedEntity,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a reason to remove this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed because password validation is removed from users/api/requests.go

@codecov-io
Copy link
codecov-io commented Feb 12, 2021

Codecov Report

Merging #1355 (0681120) into master (56d04cd) will decrease coverage by 0.02%.
The diff coverage is 60.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1355      +/-   ##
==========================================
- Coverage   60.55%   60.53%   -0.03%     
==========================================
  Files         123      123              
  Lines        9411     9416       +5     
==========================================
+ Hits         5699     5700       +1     
- Misses       3219     3221       +2     
- Partials      493      495       +2     
Impacted Files Coverage Δ
users/users.go 77.77% <ø> (-1.17%) ⬇️
users/service.go 64.13% <42.85%> (-2.53%) ⬇️
users/api/requests.go 42.30% <100.00%> (+1.56%) ⬆️
users/api/transport.go 63.57% <100.00%> (+0.25%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 56d04cd...0681120. Read the comment docs.

@@ -108,6 +111,8 @@ const (
envAuthTimeout = "MF_AUTH_GRPC_TIMEOUT"
)

var passRegex = regexp.MustCompile(mainflux.Env(envPassRegex, defPassRegex))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question: This will panic if not compile, is that expected behavior? Or we should use regexp.Compile and check for errors?

Copy link
Contributor

Choose a reason for hiding this comment

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

In my opinion nothing should fail without being logged and log sent remotely. But this is main(), so I do not know if this should be tolerated, as you will be probably looking the logs directly in console when deploying. However, I can not guarantee that, as there can be automated deployments (even without a console), and logs should be watched remotely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have used MustCompile because I saw it's used on other places:
https://github.com/mainflux/mainflux/blob/master/users/users.go#L26-L28

Copy link
Contributor
@manuio manuio Feb 22, 2021

Choose a reason for hiding this comment

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

@blokovi I would use Compile instead of MustCompile and check the errors: https://golang.org/pkg/regexp/#Compile
You can maybe also fix it in users service in this PR

Copy link
Contributor
@manuio manuio Feb 22, 2021

Choose a reason for hiding this comment

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

I'd do something like that

logger, err := logger.New(os.Stdout, cfg.logLevel)
if err != nil {
     log.Fatalf(err.Error())
}

passRegex, err := regexp.Compile(mainflux.Env(envPassRegex, defPassRegex))
if err != nil {
     passRegex, err := regexp.MustCompile(defPassRegex)
}

@@ -24,6 +25,10 @@ const (
invalidEmail = "userexample.com"
)

var (
passRegex = regexp.MustCompile("^.{8,}$")
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would rather export defPassRegex from main if you need it in multiple places.
Or set a new exported constant which will be used in other files, if you want to keep consistency (no exported def values) and then bind defPassRegex = new constant

@@ -17,6 +16,9 @@ type userReq struct {
}

func (req userReq) validate() error {
if !passRegex.MatchString(req.user.Password) {
return users.ErrMalformedEntity
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe the error should state exactly what the problem is password doesn't match policy, something like that

@@ -47,10 +46,6 @@ func (u User) Validate() error {
return ErrMalformedEntity
}

if len(u.Password) < minPassLen {
Copy link
Contributor

Choose a reason for hiding this comment

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

why we dont check password here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

two reasons:

  • we already check it on other places (validating requests for registering and password changing)
  • can't import passRegex from api package here

Copy link
Contributor

Choose a reason for hiding this comment

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

@blokovi I would check it here as it was done before and simply do:

func (req userReq) validate() error {
	return req.user.Validate()
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@manuio can't use passRegex from api package here in users (because api imports users)

Copy link
Contributor

Choose a reason for hiding this comment

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

@blokovi first remove it from the api layer :)

Comment on lines 98 to 100
invalidData := toJSON(users.User{Email: invalidEmail, Password: "password"})
invalidPasswordData := toJSON(users.User{Email: "user@example.com", Password: "pass"})
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you create consts for validEmail, validPass and invalidPass please

@@ -47,10 +46,6 @@ func (u User) Validate() error {
return ErrMalformedEntity
}

if len(u.Password) < minPassLen {
Copy link
Contributor

Choose a reason for hiding this comment

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

@blokovi I would check it here as it was done before and simply do:

func (req userReq) validate() error {
	return req.user.Validate()
}

@@ -108,6 +111,8 @@ const (
envAuthTimeout = "MF_AUTH_GRPC_TIMEOUT"
)

var passRegex = regexp.MustCompile(mainflux.Env(envPassRegex, defPassRegex))
Copy link
Contributor

Choose a reason for hiding this comment

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

F438

In my opinion nothing should fail without being logged and log sent remotely. But this is main(), so I do not know if this should be tolerated, as you will be probably looking the logs directly in console when deploying. However, I can not guarantee that, as there can be automated deployments (even without a console), and logs should be watched remotely.

@@ -111,7 +111,7 @@ const (
envAuthTimeout = "MF_AUTH_GRPC_TIMEOUT"
)

var passRegex = regexp.MustCompile(mainflux.Env(envPassRegex, defPassRegex))
// var passRegex = regexp.MustCompile(mainflux.Env(envPassRegex, defPassRegex))
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this please

users/service.go Outdated
return &usersService{
users: users,
groups: groups,
hasher: hasher,
auth: auth,
email: m,
idProvider: idp,
// passRegex: passRegex,
Copy link
Contributor
@manuio manuio Feb 23, 2021

Choose a reason for hiding this comment

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

Uncomment and use this one

users/service.go Outdated
}

// New instantiates the users service implementation
func New(users UserRepository, groups GroupRepository, hasher Hasher, auth mainflux.AuthServiceClient, m Emailer, idp mainflux.IDProvider) Service {
func New(users UserRepository, groups GroupRepository, hasher Hasher, auth mainflux.AuthServiceClient, m Emailer, idp mainflux.IDProvider, passRegex *regexp.Regexp) Service {
PassRegex = passRegex
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this one

Comment on lines 19 to 29
// if !passRegex.MatchString(req.user.Password) {
// return users.ErrPasswordPolicy
// }
return req.user.Validate()
// if err := req.user.Validate(); err != nil {
// return err
// }
// if !passRegex.MatchString(req.user.Password) {
// return users.ErrPasswordPolicy
// }
// return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove this comments please

Copy link
Collaborator
@dborovcanin dborovcanin left a comment

Choose a reason for hiding this comment

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

While I see why we added password regex as a field to the Users service, I find it a bit cleaner to use a package-level variable in the api package because we offload data validation to the transport layer (that's what we usually do). While package-level variables are generally not a good idea, this one is 1) safe for concurrent use and 2) set only on call of MakeHandler and never changed (i.e. does not hold the state and is easy to test and mock).

Comment on lines 183 to 185
if err != nil {
passRegex = regexp.MustCompile(defPassRegex)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to fail silently. We can do it similar to the other env var handling:

passRegex, err := regexp.Compile(mainflux.Env(envPassRegex, defPassRegex))
if err != nil {
    log.Fatalf("Invalid password validation rules %s\n", envPassRegex)
 }

users/service.go Outdated
@@ -66,6 +66,9 @@ var (

// ErrAssignUserToGroup indicates an error in assigning user to a group.
ErrAssignUserToGroup = errors.New("failed assigning user to a group")

// ErrPasswordPolicy indicates weak password.
ErrPasswordPolicy = errors.New("password doesn't match policy")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Using Policy terminology can be confusing; maybe ErrPasswordFormat.

@@ -302,6 +310,9 @@ func (svc usersService) ChangePassword(ctx context.Context, authToken, password,
if err != nil {
return errors.Wrap(ErrUnauthorizedAccess, err)
}
if !svc.passRegex.MatchString(password) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we validate password format in the ResetPassword metod?

Copy link
Contributor

Choose a reason for hiding this comment

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

Definitely

manuio
manuio previously approved these changes Feb 26, 2021
Copy link
Contributor
@manuio manuio left a comment

Choose a reason for hiding this comment

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

LGTM

mteodor
mteodor previously approved these changes Mar 1, 2021
dborovcanin
dborovcanin previously approved these changes Mar 1, 2021
manuio
manuio previously approved these changes Mar 1, 2021
Copy link
Contributor
@manuio manuio left a comment

Choose a reason for hiding this comment

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

LGTM

mteodor
mteodor previously approved these changes Mar 1, 2021
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
blokovi added 17 commits March 1, 2021 12:42
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
… var

Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
Signed-off-by: Ivan Milosevic <iva@blokovi.com>
@blokovi blokovi dismissed stale reviews from mteodor and manuio via d1f3985 March 1, 2021 11:42
Copy link
Contributor
@drasko drasko left a comment

Choose a reason for hiding this comment

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

LGTM

@drasko drasko merged commit 7bcaa32 into absmach:master Mar 1, 2021
fbugarski pushed a commit to fbugarski/mainflux that referenced this pull request Mar 8, 2021
* read and validate regex envar

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* pass regexp to user/api

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* resolve conflicts

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* use exported regexp variable

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* move password validation from users package

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* remove dead code

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* add password change request

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* move regexp from api to users package

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* fix tests

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* remove commented code

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* add regexp as field in userService, remove it as user exported global var

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* add passwd validation in service

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* Add psswd validation for change password in service

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* add password validation in password reset

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* Remove password validation from user validation test

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* Replace email and passwords in test with constants

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* compile error not fail silently

Signed-off-by: Ivan Milosevic <iva@blokovi.com>

* fix tempate path

Signed-off-by: Ivan Milosevic <iva@blokovi.com>
@blokovi blokovi deleted the MF-1317 branch March 11, 2021 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Minimal password length limitation
7 participants
0