// SessionGet is used to get info for a particular session func (s *HTTPServer) SessionGet(resp http.ResponseWriter, req *http.Request) (interface{}, error) { args := structs.SessionSpecificRequest{} if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done { return nil, nil } // Pull out the session id args.Session = strings.TrimPrefix(req.URL.Path, "/v1/session/info/") if args.Session == "" { resp.WriteHeader(400) resp.Write([]byte("Missing session")) return nil, nil } var out structs.IndexedSessions defer setMeta(resp, &out.QueryMeta) if err := s.agent.RPC("Session.Get", &args, &out); err != nil { return nil, err } // Use empty list instead of nil if out.Sessions == nil { out.Sessions = make(structs.Sessions, 0) } return out.Sessions, nil }
// SessionRenew is used to renew the TTL on an existing TTL session func (s *HTTPServer) SessionRenew(resp http.ResponseWriter, req *http.Request) (interface{}, error) { // Mandate a PUT request if req.Method != "PUT" { resp.WriteHeader(405) return nil, nil } args := structs.SessionSpecificRequest{} if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done { return nil, nil } // Pull out the session id args.Session = strings.TrimPrefix(req.URL.Path, "/v1/session/renew/") if args.Session == "" { resp.WriteHeader(400) resp.Write([]byte("Missing session")) return nil, nil } var out structs.IndexedSessions if err := s.agent.RPC("Session.Renew", &args, &out); err != nil { return nil, err } else if out.Sessions == nil { resp.WriteHeader(404) resp.Write([]byte(fmt.Sprintf("Session id '%s' not found", args.Session))) return nil, nil } return out.Sessions, nil }
func TestSession_Renew_ACLDeny(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" c.ACLMasterToken = "root" c.ACLDefaultPolicy = "deny" c.ACLEnforceVersion8 = false }) defer os.RemoveAll(dir1) defer s1.Shutdown() codec := rpcClient(t, s1) defer codec.Close() testutil.WaitForLeader(t, s1.RPC, "dc1") // Create the ACL. req := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: ` session "foo" { policy = "write" } `, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var token string if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &req, &token); err != nil { t.Fatalf("err: %v", err) } // Just add a node. s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) // Create a session. The token won't matter here since we don't have // version 8 ACL enforcement on yet. arg := structs.SessionRequest{ Datacenter: "dc1", Op: structs.SessionCreate, Session: structs.Session{ Node: "foo", Name: "my-session", }, } var id string if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &id); err != nil { t.Fatalf("err: %v", err) } // Renew without a token should go through without version 8 ACL // enforcement. renewR := structs.SessionSpecificRequest{ Datacenter: "dc1", Session: id, } var session structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session); err != nil { t.Fatalf("err: %v", err) } // Now turn on version 8 enforcement and the renew should be rejected. s1.config.ACLEnforceVersion8 = true err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session) if err == nil || !strings.Contains(err.Error(), permissionDenied) { t.Fatalf("err: %v", err) } // Set the token and it should go through. renewR.Token = token if err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session); err != nil { t.Fatalf("err: %v", err) } }
func TestSession_Get_List_NodeSessions_ACLFilter(t *testing.T) { dir1, s1 := testServerWithConfig(t, func(c *Config) { c.ACLDatacenter = "dc1" c.ACLMasterToken = "root" c.ACLDefaultPolicy = "deny" c.ACLEnforceVersion8 = false }) defer os.RemoveAll(dir1) defer s1.Shutdown() codec := rpcClient(t, s1) defer codec.Close() testutil.WaitForLeader(t, s1.RPC, "dc1") // Create the ACL. req := structs.ACLRequest{ Datacenter: "dc1", Op: structs.ACLSet, ACL: structs.ACL{ Name: "User token", Type: structs.ACLTypeClient, Rules: ` session "foo" { policy = "read" } `, }, WriteRequest: structs.WriteRequest{Token: "root"}, } var token string if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &req, &token); err != nil { t.Fatalf("err: %v", err) } // Create a node and a session. s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}) arg := structs.SessionRequest{ Datacenter: "dc1", Op: structs.SessionCreate, Session: structs.Session{ Node: "foo", }, WriteRequest: structs.WriteRequest{Token: "root"}, } var out string if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil { t.Fatalf("err: %v", err) } // Perform all the read operations, which should go through since version // 8 ACL enforcement isn't enabled. getR := structs.SessionSpecificRequest{ Datacenter: "dc1", Session: out, } { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } listR := structs.DCSpecificRequest{ Datacenter: "dc1", } { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } nodeR := structs.NodeSpecificRequest{ Datacenter: "dc1", Node: "foo", } { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } // Now turn on version 8 enforcement and make sure everything is empty. s1.config.ACLEnforceVersion8 = true { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 0 { t.Fatalf("bad: %v", sessions.Sessions) } } { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 0 { t.Fatalf("bad: %v", sessions.Sessions) } } { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 0 { t.Fatalf("bad: %v", sessions.Sessions) } } // Finally, supply the token and make sure the reads are allowed. getR.Token = token { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } listR.Token = token { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } nodeR.Token = token { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 1 { t.Fatalf("bad: %v", sessions.Sessions) } } // Try to get a session that doesn't exist to make sure that's handled // correctly by the filter (it will get passed a nil slice). getR.Session = "adf4238a-882b-9ddc-4a9d-5b6758e4159e" { var sessions structs.IndexedSessions if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil { t.Fatalf("err: %v", err) } if len(sessions.Sessions) != 0 { t.Fatalf("bad: %v", sessions.Sessions) } } }