Skip to content

Commit

Permalink
Merge pull request #8594 from mitake/auth-priority
Browse files Browse the repository at this point in the history
RFC: etcdserver: swap priority of cert CN and username + password
  • Loading branch information
xiang90 authored Sep 26, 2017
2 parents 2240b6a + f815d9a commit 554298d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Documentation/op-guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,4 @@ Otherwise, all `etcdctl` commands remain the same. Users and roles can still be

## Using TLS Common Name

If an etcd server is launched with the option `--client-cert-auth=true`, the field of Common Name (CN) in the client's TLS cert will be used as an etcd user. In this case, the common name authenticates the user and the client does not need a password.
If an etcd server is launched with the option `--client-cert-auth=true`, the field of Common Name (CN) in the client's TLS cert will be used as an etcd user. In this case, the common name authenticates the user and the client does not need a password. Note that if both of 1. `--client-cert-auth=true` is passed and CN is provided by the client, and 2. username and password are provided by the client, the username and password based authentication is prioritized.
72 changes: 64 additions & 8 deletions e2e/ctl_v3_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func TestCtlV3AuthEndpointHealth(t *testing.T) {
testCtl(t, authTestEndpointHealth, withQuorum())
}
func TestCtlV3AuthSnapshot(t *testing.T) { testCtl(t, authTestSnapshot) }
func TestCtlV3AuthCertCNAndUsername(t *testing.T) {
testCtl(t, authTestCertCNAndUsername, withCfg(configClientTLSCertAuth))
}

func authEnableTest(cx ctlCtx) {
if err := authEnable(cx); err != nil {
Expand Down Expand Up @@ -557,17 +560,18 @@ func authTestMemberUpdate(cx ctlCtx) {
}

func authTestCertCN(cx ctlCtx) {
if err := ctlV3User(cx, []string{"add", "etcd", "--interactive=false"}, "User etcd created", []string{""}); err != nil {
if err := authEnable(cx); err != nil {
cx.t.Fatal(err)
}
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil {

cx.user, cx.pass = "root", "root"
if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
cx.t.Fatal(err)
}
if err := ctlV3User(cx, []string{"grant-role", "etcd", "test-role"}, "Role test-role is granted to user etcd", nil); err != nil {
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil {
cx.t.Fatal(err)
}
cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo")
if err := spawnWithExpect(cmd, "Role test-role updated"); err != nil {
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role"}, "Role test-role is granted to user example.com", nil); err != nil {
cx.t.Fatal(err)
}

Expand All @@ -579,13 +583,13 @@ func authTestCertCN(cx ctlCtx) {
// try a granted key
cx.user, cx.pass = "", ""
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
cx.t.Fatal(err)
cx.t.Error(err)
}

// try a non granted key
cx.user, cx.pass = "", ""
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err == nil {
cx.t.Fatal(err)
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
cx.t.Error(err)
}
}

Expand Down Expand Up @@ -957,3 +961,55 @@ func authTestEndpointHealth(cx ctlCtx) {
cx.t.Fatalf("endpointStatusTest ctlV3EndpointHealth error (%v)", err)
}
}

func authTestCertCNAndUsername(cx ctlCtx) {
if err := authEnable(cx); err != nil {
cx.t.Fatal(err)
}

cx.user, cx.pass = "root", "root"
authSetupTestUser(cx)

if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
cx.t.Fatal(err)
}
if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), "Role test-role-cn created"); err != nil {
cx.t.Fatal(err)
}
if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role-cn"}, "Role test-role-cn is granted to user example.com", nil); err != nil {
cx.t.Fatal(err)
}

// grant a new key for CN based user
if err := ctlV3RoleGrantPermission(cx, "test-role-cn", grantingPerm{true, true, "hoo", "", false}); err != nil {
cx.t.Fatal(err)
}

// grant a new key for username based user
if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, "bar", "", false}); err != nil {
cx.t.Fatal(err)
}

// try a granted key for CN based user
cx.user, cx.pass = "", ""
if err := ctlV3Put(cx, "hoo", "bar", ""); err != nil {
cx.t.Error(err)
}

// try a granted key for username based user
cx.user, cx.pass = "test-user", "pass"
if err := ctlV3Put(cx, "bar", "bar", ""); err != nil {
cx.t.Error(err)
}

// try a non granted key for both of them
cx.user, cx.pass = "", ""
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
cx.t.Error(err)
}

cx.user, cx.pass = "test-user", "pass"
if err := ctlV3PutFailPerm(cx, "baz", "bar"); err != nil {
cx.t.Error(err)
}
}
14 changes: 8 additions & 6 deletions etcdserver/v3_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,12 +686,14 @@ func (s *EtcdServer) linearizableReadNotify(ctx context.Context) error {
}

func (s *EtcdServer) AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) {
if s.Cfg.ClientCertAuthEnabled {
authInfo := s.AuthStore().AuthInfoFromTLS(ctx)
if authInfo != nil {
return authInfo, nil
}
authInfo, err := s.AuthStore().AuthInfoFromCtx(ctx)
if authInfo != nil || err != nil {
return authInfo, err
}
if !s.Cfg.ClientCertAuthEnabled {
return nil, nil
}
authInfo = s.AuthStore().AuthInfoFromTLS(ctx)
return authInfo, nil

return s.AuthStore().AuthInfoFromCtx(ctx)
}

0 comments on commit 554298d

Please sign in to comment.