func TestACL_MultiDC_Found(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" c.ACLMasterToken = "root" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() dir2, s2 := testServerWithConfig(t, func(c *Config) { c.Datacenter = "dc2" c.ACLDatacenter = "dc1" // Enable ACLs! }) defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfWANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinWAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } testutil.WaitForLeader(t, s1.RPC, "dc1") testutil.WaitForLeader(t, s1.RPC, "dc2") // Create a new token arg := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: testACLPolicy, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var id string if err := s1.RPC("ACL.Apply", &arg, &id); err != nil { t.Fatalf("err: %v", err) } // Token should resolve acl, err := s2.resolveToken(id) if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy if acl.KeyRead("bar") { t.Fatalf("unexpected read") } if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } }
func TestACL_Authority_Management(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" // Enable ACLs! c.ACLMasterToken = "foobar" c.ACLDefaultPolicy = "deny" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() testutil.WaitForLeader(t, s1.RPC, "dc1") // Resolve the token acl, err := s1.resolveToken("foobar") if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy, should allow all if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } }
func TestACL_Authority_Found(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" // Enable ACLs! c.ACLMasterToken = "root" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() testutil.WaitForLeader(t, s1.RPC, "dc1") // Create a new token arg := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: testACLPolicy, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var id string if err := s1.RPC("ACL.Apply", &arg, &id); err != nil { t.Fatalf("err: %v", err) } // Resolve the token acl, err := s1.resolveToken(id) if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy if acl.KeyRead("bar") { t.Fatalf("unexpected read") } if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } }
func TestACL_NonAuthority_Management(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" // Enable ACLs! c.ACLMasterToken = "foobar" c.ACLDefaultPolicy = "deny" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() dir2, s2 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" // Enable ACLs! c.ACLDefaultPolicy = "deny" c.Bootstrap = false // Disable bootstrap }) defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfLANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinLAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } testutil.WaitForResult(func() (bool, error) { p1, _ := s1.raftPeers.Peers() return len(p1) == 2, errors.New(fmt.Sprintf("%v", p1)) }, func(err error) { t.Fatalf("should have 2 peers: %v", err) }) testutil.WaitForLeader(t, s1.RPC, "dc1") // find the non-authoritative server var nonAuth *Server if !s1.IsLeader() { nonAuth = s1 } else { nonAuth = s2 } // Resolve the token acl, err := nonAuth.resolveToken("foobar") if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy, should allow all if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } }
// Get is used to lookup a single key. func (k *KVS) Get(args *structs.KeyRequest, reply *structs.IndexedDirEntries) error { if done, err := k.srv.forward("KVS.Get", args, args, reply); done { return err } acl, err := k.srv.resolveToken(args.Token) if err != nil { return err } // Get the local state state := k.srv.fsm.State() return k.srv.blockingRPC( &args.QueryOptions, &reply.QueryMeta, state.GetKVSWatch(args.Key), func() error { index, ent, err := state.KVSGet(args.Key) if err != nil { return err } if acl != nil && !acl.KeyRead(args.Key) { ent = nil } if ent == nil { // Must provide non-zero index to prevent blocking // Index 1 is impossible anyways (due to Raft internals) if index == 0 { reply.Index = 1 } else { reply.Index = index } reply.Entries = nil } else { reply.Index = ent.ModifyIndex reply.Entries = structs.DirEntries{ent} } return nil }) }
func TestACL_NonAuthority_Found(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" c.ACLMasterToken = "root" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() dir2, s2 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" // Enable ACLs! c.Bootstrap = false // Disable bootstrap }) defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfLANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinLAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } testutil.WaitForResult(func() (bool, error) { p1, _ := s1.raftPeers.Peers() return len(p1) == 2, errors.New(fmt.Sprintf("%v", p1)) }, func(err error) { t.Fatalf("should have 2 peers: %v", err) }) testutil.WaitForLeader(t, s1.RPC, "dc1") // Create a new token arg := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: testACLPolicy, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var id string if err := s1.RPC("ACL.Apply", &arg, &id); err != nil { t.Fatalf("err: %v", err) } // find the non-authoritative server var nonAuth *Server if !s1.IsLeader() { nonAuth = s1 } else { nonAuth = s2 } // Token should resolve acl, err := nonAuth.resolveToken(id) if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy if acl.KeyRead("bar") { t.Fatalf("unexpected read") } if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } }
func TestACL_Replication(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" c.ACLMasterToken = "root" }) defer os.RemoveAll(dir1) defer s1.Shutdown() client := rpcClient(t, s1) defer client.Close() dir2, s2 := testServerWithConfig(t, func(c *Config) { c.Datacenter = "dc2" c.ACLDatacenter = "dc1" c.ACLDefaultPolicy = "deny" c.ACLDownPolicy = "extend-cache" c.ACLReplicationToken = "root" c.ACLReplicationInterval = 0 c.ACLReplicationApplyLimit = 1000000 }) defer os.RemoveAll(dir2) defer s2.Shutdown() dir3, s3 := testServerWithConfig(t, func(c *Config) { c.Datacenter = "dc3" c.ACLDatacenter = "dc1" c.ACLDownPolicy = "deny" c.ACLReplicationToken = "root" c.ACLReplicationInterval = 0 c.ACLReplicationApplyLimit = 1000000 }) defer os.RemoveAll(dir3) defer s3.Shutdown() // Try to join. addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfWANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinWAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } if _, err := s3.JoinWAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } testutil.WaitForLeader(t, s1.RPC, "dc1") testutil.WaitForLeader(t, s1.RPC, "dc2") testutil.WaitForLeader(t, s1.RPC, "dc3") // Create a new token. arg := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: testACLPolicy, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var id string if err := s1.RPC("ACL.Apply", &arg, &id); err != nil { t.Fatalf("err: %v", err) } // Wait for replication to occur. testutil.WaitForResult(func() (bool, error) { _, acl, err := s2.fsm.State().ACLGet(id) if err != nil { return false, err } if acl == nil { return false, nil } _, acl, err = s3.fsm.State().ACLGet(id) if err != nil { return false, err } if acl == nil { return false, nil } return true, nil }, func(err error) { t.Fatalf("ACLs didn't converge") }) // Kill the ACL datacenter. s1.Shutdown() // Token should resolve on s2, which has replication + extend-cache. acl, err := s2.resolveToken(id) if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy if acl.KeyRead("bar") { t.Fatalf("unexpected read") } if !acl.KeyRead("foo/test") { t.Fatalf("unexpected failed read") } // Although s3 has replication, and we verified that the ACL is there, // it can not be used because of the down policy. acl, err = s3.resolveToken(id) if err != nil { t.Fatalf("err: %v", err) } if acl == nil { t.Fatalf("missing acl") } // Check the policy. if acl.KeyRead("bar") { t.Fatalf("unexpected read") } if acl.KeyRead("foo/test") { t.Fatalf("unexpected read") } }