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

*: support creating a user without password #9817

Merged
merged 4 commits into from
Jun 1, 2019
Merged

Conversation

mitake
Copy link
Contributor

@mitake mitake commented Jun 7, 2018

This commit adds a feature for creating a user without password. The
purpose of the feature is reducing attack surface by configuring bad
passwords (CN based auth will be allowed for the user).

The feature can be used with --no-password of etcdctl user add
command.

Fix #9590

@mitake
Copy link
Contributor Author

mitake commented Jun 7, 2018

This PR isn't tested yet. I'll do it and add e2e test cases later.

/cc @crielly @joelegasse

@gyuho gyuho requested a review from joelegasse June 7, 2018 17:55
@mitake mitake force-pushed the no-password branch 4 times, most recently from e52ceb2 to bc20594 Compare June 13, 2018 04:51
@mitake
Copy link
Contributor Author

mitake commented Jun 13, 2018

@joelegasse I added the test cases, could you take a look? It seems that the travis failures aren't related to the change.

@mitake mitake changed the title WIP, DO NOT MERGE *: support creating a user without password *: support creating a user without password Jun 13, 2018
@jpbetz
Copy link
Contributor

jpbetz commented Jun 13, 2018

Let's document this carefully. The behavior of the system for users with no password needs to be clear so that the security implications can be reasoned about easily.

@mitake
Copy link
Contributor Author

mitake commented Jun 14, 2018

@jpbetz thanks for pointing out, I'll update the doc later.

@mitake
Copy link
Contributor Author

mitake commented Jun 14, 2018

@jpbetz
Copy link
Contributor

jpbetz commented Jun 14, 2018

Docs look great @mitake. Thanks!

@gyuho
Copy link
Contributor

gyuho commented Jun 14, 2018

@mitake Can you fix the CI failure https://travis-ci.org/coreos/etcd/jobs/392115574#L898-L912?

Copy link
Contributor

@jpbetz jpbetz left a comment

Choose a reason for hiding this comment

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

Code and doc changes look good to me. Just want to check on the backward compatibility before approving.

Thanks!

clientv3/auth.go Outdated
@@ -61,7 +61,7 @@ type Auth interface {
AuthDisable(ctx context.Context) (*AuthDisableResponse, error)

// UserAdd adds a new user to an etcd cluster.
UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error)
UserAdd(ctx context.Context, name string, password string, noPassword bool) (*AuthUserAddResponse, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a source backward incompatible change in the client. Is this acceptable? The only alternative I can think of would be to introduce an additional UserAddNoPassword function, or similar.

cc @gyuho for compatibility expectations of changes to client

Copy link
Contributor

Choose a reason for hiding this comment

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

@jpbetz Oh good catch.

UserAddNoPassword sounds better for compatibilities.

/cc @mitake

Copy link
Contributor

Choose a reason for hiding this comment

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

One other alternative would be to introduce a UserAddWithOptons(..., opts... UserAddOption) function as well as a WithNoPassword UserAddOption. This would future proof the API against additions of more UserAdd parameters in the future. I'm not sure if that's justified here or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing out. I'll introduce UserAddWithOptons. It would be good for expanding in the future as @jpbetz says.

clientv3/auth.go Outdated
func (auth *authClient) UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error) {
resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password}, auth.callOpts...)
func (auth *authClient) UserAdd(ctx context.Context, name string, password string, noPassword bool) (*AuthUserAddResponse, error) {
resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password, NoPassword: noPassword}, auth.callOpts...)
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above. Should we retain backward compatibility?

@mitake
Copy link
Contributor Author

mitake commented Jun 18, 2018

@jpbetz @gyuho updated for not breaking source level compatibility. Could you take a look?

@mitake mitake force-pushed the no-password branch 2 times, most recently from 357a5b7 to 29a8e61 Compare June 18, 2018 09:36
Copy link
Contributor

@joelegasse joelegasse left a comment

Choose a reason for hiding this comment

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

Personally, this seems more complex where a simple length check on the password should work just as well.

I think having the extra flag in addition to always sending in a password argument is strange. At the CLI level, I would still suggest having the --no-password flag just to signal that it's intended, but once at the protobuf/API level, an empty password could signal "disable password auth for this user".

Then, instead of checking an options field in the user for NoPassword, it's just if len(u.Password) == 0 {}.

auth/store.go Outdated
)
} else {
plog.Errorf("failed to hash password: %s", err)
hashed := make([]byte, 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor note: var hashed []byte should be used here instead of make-ing a zero-length slice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I'll fix it soon

@mitake
Copy link
Contributor Author

mitake commented Jun 19, 2018

@joelegasse handling an empty password as a special case breaks existing semantics of the RPC so I don't want to do it. How do you think? @jpbetz @gyuho

@mitake mitake force-pushed the no-password branch 2 times, most recently from 3709a11 to f9b7766 Compare June 19, 2018 05:33
@mitake
Copy link
Contributor Author

mitake commented Jun 19, 2018

I couldn't reproduce the travis fail on my local environment. It would be freaky.

@joelegasse
Copy link
Contributor

@mitake Do you have time to rebase this PR? You were correct that the current RPC allows users to be created/authenticated with an empty password, so that wouldn't be a backwards-compatible change.

If not, I can take this over and get it cleaned up for more thorough testing.

@joelegasse joelegasse dismissed their stale review July 23, 2018 14:50

Suggested changes were not feasible

@mitake
Copy link
Contributor Author

mitake commented Jul 23, 2018

@joelegasse probably I will be able to rebase this weekend. Do you need to test it earlier?

@joelegasse
Copy link
Contributor

No, that should be fine. Thank you :-)

@mitake mitake force-pushed the no-password branch 2 times, most recently from b3dcbeb to fe92b77 Compare January 9, 2019 15:41
@mitake
Copy link
Contributor Author

mitake commented Jan 9, 2019

@gyuho I'm still seeing a confusing build error like below, do you know why does this happen? It would be related to recent path change? I'll work on it probably tomorrow.

$ make
github.com/coreos/etcd/clientv3
# github.com/coreos/etcd/clientv3
../../github.com/coreos/etcd/clientv3/auth.go:121:72: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.AuthEnable
../../github.com/coreos/etcd/clientv3/auth.go:126:74: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.AuthDisable
../../github.com/coreos/etcd/clientv3/auth.go:131:152: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserAdd
../../github.com/coreos/etcd/clientv3/auth.go:136:144: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserAdd
../../github.com/coreos/etcd/clientv3/auth.go:141:86: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserDelete
../../github.com/coreos/etcd/clientv3/auth.go:146:122: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserChangePassword
../../github.com/coreos/etcd/clientv3/auth.go:151:104: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserGrantRole
../../github.com/coreos/etcd/clientv3/auth.go:156:80: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserGet
../../github.com/coreos/etcd/clientv3/auth.go:161:72: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserList
../../github.com/coreos/etcd/clientv3/auth.go:166:106: cannot use auth.callOpts (type []"github.com/coreos/etcd/vendor/google.golang.org/grpc".CallOption) as type []"go.etcd.io/etcd/vendor/google.golang.org/grpc".CallOption in argument to auth.remote.UserRevokeRole
../../github.com/coreos/etcd/clientv3/auth.go:166:106: too many errors
Makefile:15: recipe for target 'build' failed
make: *** [build] Error 2

@mitake
Copy link
Contributor Author

mitake commented Jan 9, 2019

@wenjiaswe This PR add a new member to etcdserverpb.AuthenticateRequest. I'm not sure but would like to let you know about this because it might affect your downgrade functionality. The functionality might need to care about WAL entries which have the new member (IIRC, protobuf generated code can ignore a member which isn't in a definition?).

@mitake
Copy link
Contributor Author

mitake commented Apr 30, 2019

@gyuho @jpbetz sorry for my late update. I fixed the build problem so the PR is ready to be reviewed again. I think the branch includes fixes for all comments from you. Could you take a look?

@mitake mitake force-pushed the no-password branch 2 times, most recently from d8ea60d to bb20f87 Compare May 1, 2019 09:32
@mitake
Copy link
Contributor Author

mitake commented May 1, 2019

The unit test is failing because of data race. I opened a new issue here: #10697 The issue seems to be independent from this PR.

@codecov-io
Copy link

codecov-io commented May 1, 2019

Codecov Report

Merging #9817 into master will increase coverage by 0.88%.
The diff coverage is 26.92%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #9817      +/-   ##
==========================================
+ Coverage    62.3%   63.19%   +0.88%     
==========================================
  Files         392      392              
  Lines       37158    37183      +25     
==========================================
+ Hits        23152    23498     +346     
+ Misses      12438    12102     -336     
- Partials     1568     1583      +15
Impacted Files Coverage Δ
etcdctl/ctlv3/command/user_command.go 34.81% <4.54%> (-0.96%) ⬇️
auth/store.go 68.5% <42.3%> (+17.71%) ⬆️
clientv3/auth.go 62.33% <50%> (-2.53%) ⬇️
pkg/transport/timeout_conn.go 60% <0%> (-20%) ⬇️
pkg/adt/interval_tree.go 78.67% <0%> (-9.91%) ⬇️
etcdserver/api/v3rpc/lease.go 69.31% <0%> (-5.69%) ⬇️
proxy/grpcproxy/watcher.go 85.71% <0%> (-4.09%) ⬇️
clientv3/concurrency/election.go 79.68% <0%> (-2.35%) ⬇️
etcdserver/api/v3rpc/watch.go 76.14% <0%> (-2.29%) ⬇️
etcdserver/api/rafthttp/msgappv2_codec.go 69.56% <0%> (-1.74%) ⬇️
... and 24 more

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 dc6885d...96a7ff0. Read the comment docs.

@mitake
Copy link
Contributor Author

mitake commented May 17, 2019

This PR depends on the fix introduced in #10739

@mitake
Copy link
Contributor Author

mitake commented May 29, 2019

@gyuho @jpbetz now all CIs are passed. Could you take a look?

@gyuho
Copy link
Contributor

gyuho commented May 29, 2019

@mitake Sorry for delay. Will take a look by today.

@gyuho
Copy link
Contributor

gyuho commented May 30, 2019

@mitake Can you also update changelog, with rebasing to trigger CIs?

mitake and others added 4 commits May 30, 2019 21:59
This commit adds a feature for creating a user without password. The
purpose of the feature is reducing attack surface by configuring bad
passwords (CN based auth will be allowed for the user).

The feature can be used with `--no-password` of `etcdctl user add`
command.

Fix etcd-io#9590
@mitake
Copy link
Contributor Author

mitake commented May 30, 2019

@gyuho done, could you take a look? I found a fleaky test which wouldn't be related to this PR. Issue for the test is here #10774

@gyuho gyuho merged commit cdca488 into etcd-io:master Jun 1, 2019
@mitake mitake deleted the no-password branch June 1, 2019 06:06
@jingyih
Copy link
Contributor

jingyih commented Jun 6, 2019

Hi @mitake, I noticed an e2e test failure which might be related to this PR: https://semaphoreci.com/etcd-io/etcd/branches/pull-request-10797/builds/3

I took a quick look, maybe this function call also needs to be updated?
https://github.com/mitake/etcd/blob/96a7ff0a62ce3f52aad258289bd0f25d1a781a1b/tests/e2e/v3_curl_test.go#L199

@mitake
Copy link
Contributor Author

mitake commented Jun 6, 2019

@jingyih thanks a lot for pointing out! Yeah probably that's the reason. It is a little bit surprising for me because such an uninitialized variable is zero cleared by go. So the behavior of the function would be deterministic and the tests rely on it shouldn't be flaky. Probably protobuf layer has a pitfall related to this? I'll take a look but please let me know if you know something related to the behavior.

Anyway I opened #10800 Could you take a look?

BTW the link to the result of semaphore CI seems to be expired... I hope semaphore to keep results longer :(

@jingyih
Copy link
Contributor

jingyih commented Jun 6, 2019

We should probably move all CI tests to Travis, now that it can run 13 jobs in parallel.

The failed tests was TestV3CurlAuth and TestV3CurlAuthClientTLSCertAuth. They are fixed by #10800.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Ability to create users without a password
6 participants