diff --git a/consul/acl_test.go b/consul/acl_test.go index 3cb9375c3c..2fabcbee99 100644 --- a/consul/acl_test.go +++ b/consul/acl_test.go @@ -674,103 +674,6 @@ func TestACL_MultiDC_Found(t *testing.T) { } } -func TestACL_applyDiscoveryACLs(t *testing.T) { - dir, srv := testServerWithConfig(t, func(c *Config) { - c.ACLDatacenter = "dc1" - c.ACLMasterToken = "root" - c.ACLDefaultPolicy = "deny" - }) - defer os.RemoveAll(dir) - defer srv.Shutdown() - - client := rpcClient(t, srv) - defer client.Close() - - testutil.WaitForLeader(t, client.Call, "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 := client.Call("ACL.Apply", &arg, &id); err != nil { - t.Fatalf("err: %v", err) - } - - // Register a service - regArg := structs.RegisterRequest{ - Datacenter: "dc1", - Node: srv.config.NodeName, - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "redis", - Service: "redis", - }, - Check: &structs.HealthCheck{ - CheckID: "service:redis", - Name: "service:redis", - ServiceID: "redis", - }, - WriteRequest: structs.WriteRequest{Token: "root"}, - } - if err := client.Call("Catalog.Register", ®Arg, nil); err != nil { - t.Fatalf("err: %s", err) - } - - // Try querying the catalog - opt := structs.DCSpecificRequest{ - Datacenter: "dc1", - QueryOptions: structs.QueryOptions{ - Token: id, - }, - } - services := structs.IndexedServices{} - if err := client.Call("Catalog.ListServices", &opt, &services); err != nil { - t.Fatalf("err: %s", err) - } - - // Check if the service was returned - if _, ok := services.Services["redis"]; !ok { - t.Fatalf("bad: %#v", services.Services) - } - - // Register a service which should be denied - regArg = structs.RegisterRequest{ - Datacenter: "dc1", - Node: srv.config.NodeName, - Address: "127.0.0.1", - Service: &structs.NodeService{ - ID: "rabbit", - Service: "rabbit", - }, - Check: &structs.HealthCheck{ - CheckID: "service:rabbit", - Name: "service:rabbit", - ServiceID: "rabbit", - }, - WriteRequest: structs.WriteRequest{Token: "root"}, - } - if err := client.Call("Catalog.Register", ®Arg, nil); err != nil { - t.Fatalf("err: %s", err) - } - - // Check that the service was omitted from the result - services = structs.IndexedServices{} - if err := client.Call("Catalog.ListServices", &opt, &services); err != nil { - t.Fatalf("err: %s", err) - } - if _, ok := services.Services["rabbit"]; ok { - t.Fatalf("bad: %#v", services.Services) - } -} - var testACLPolicy = ` key "" { policy = "deny" @@ -778,7 +681,4 @@ key "" { key "foo/" { policy = "write" } -service "redis" { - policy = "read" -} ` diff --git a/consul/catalog_endpoint_test.go b/consul/catalog_endpoint_test.go index b84c9438ac..2f53885a93 100644 --- a/consul/catalog_endpoint_test.go +++ b/consul/catalog_endpoint_test.go @@ -778,6 +778,162 @@ func TestCatalogRegister_FailedCase1(t *testing.T) { } } +func TestServer_applyDiscoveryACLs(t *testing.T) { + dir, srv := testServerWithConfig(t, func(c *Config) { + c.ACLDatacenter = "dc1" + c.ACLMasterToken = "root" + c.ACLDefaultPolicy = "deny" + }) + defer os.RemoveAll(dir) + defer srv.Shutdown() + + client := rpcClient(t, srv) + defer client.Close() + + testutil.WaitForLeader(t, client.Call, "dc1") + + // Create a new token + arg := structs.ACLRequest{ + Datacenter: "dc1", + Op: structs.ACLSet, + ACL: structs.ACL{ + Name: "User token", + Type: structs.ACLTypeClient, + Rules: testRegisterRules, + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + var id string + if err := client.Call("ACL.Apply", &arg, &id); err != nil { + t.Fatalf("err: %v", err) + } + + // Register a service + regArg := structs.RegisterRequest{ + Datacenter: "dc1", + Node: srv.config.NodeName, + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "foo", + Service: "foo", + }, + Check: &structs.HealthCheck{ + CheckID: "service:foo", + Name: "service:foo", + ServiceID: "foo", + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + if err := client.Call("Catalog.Register", ®Arg, nil); err != nil { + t.Fatalf("err: %s", err) + } + + // Register a service which should be denied + regArg = structs.RegisterRequest{ + Datacenter: "dc1", + Node: srv.config.NodeName, + Address: "127.0.0.1", + Service: &structs.NodeService{ + ID: "bar", + Service: "bar", + }, + Check: &structs.HealthCheck{ + CheckID: "service:bar", + Name: "service:bar", + ServiceID: "bar", + }, + WriteRequest: structs.WriteRequest{Token: "root"}, + } + if err := client.Call("Catalog.Register", ®Arg, nil); err != nil { + t.Fatalf("err: %s", err) + } + + // Catalog.ListServices properly filters and returns services + { + opt := structs.DCSpecificRequest{ + Datacenter: "dc1", + QueryOptions: structs.QueryOptions{Token: id}, + } + reply := structs.IndexedServices{} + if err := client.Call("Catalog.ListServices", &opt, &reply); err != nil { + t.Fatalf("err: %s", err) + } + if _, ok := reply.Services["foo"]; !ok { + t.Fatalf("bad: %#v", reply.Services) + } + if _, ok := reply.Services["bar"]; ok { + t.Fatalf("bad: %#v", reply.Services) + } + } + + // Catalog.ServiceNodes returns services we have access to + { + opt := structs.ServiceSpecificRequest{ + Datacenter: "dc1", + ServiceName: "foo", + QueryOptions: structs.QueryOptions{Token: id}, + } + reply := structs.IndexedServiceNodes{} + if err := client.Call("Catalog.ServiceNodes", &opt, &reply); err != nil { + t.Fatalf("err: %s", err) + } + found := false + for _, sn := range reply.ServiceNodes { + if sn.ServiceID == "foo" { + found = true + break + } + } + if !found { + t.Fatalf("bad: %#v", reply.ServiceNodes) + } + } + + // Catalog.ServiceNodes filters services we can't access + { + opt := structs.ServiceSpecificRequest{ + Datacenter: "dc1", + ServiceName: "bar", + QueryOptions: structs.QueryOptions{Token: id}, + } + reply := structs.IndexedServiceNodes{} + if err := client.Call("Catalog.ServiceNodes", &opt, &reply); err != nil { + t.Fatalf("err: %s", err) + } + for _, sn := range reply.ServiceNodes { + if sn.ServiceID == "bar" { + t.Fatalf("bad: %#v", reply.ServiceNodes) + } + } + } + + // Catalog.NodeServices filters and returns services properly + { + opt := structs.NodeSpecificRequest{ + Datacenter: "dc1", + Node: srv.config.NodeName, + QueryOptions: structs.QueryOptions{Token: id}, + } + reply := structs.IndexedNodeServices{} + if err := client.Call("Catalog.NodeServices", &opt, &reply); err != nil { + t.Fatalf("err: %s", err) + } + found := false + for _, svc := range reply.NodeServices.Services { + if svc.ID == "bar" { + t.Fatalf("bad: %#v", reply.NodeServices.Services) + } + if svc.ID == "foo" { + found = true + break + } + } + if !found { + t.Fatalf("bad: %#v", reply.NodeServices) + } + } +} + var testRegisterRules = ` service "foo" { policy = "write"