diff --git a/apps/consul_proxy/src/consul_proxy.app.src b/apps/consul_proxy/src/consul_proxy.app.src index e2ea079a5fb0b20d942c85da886cf33fd4e2d342..5931a055429864700c342706dbbca06c70802e1c 100644 --- a/apps/consul_proxy/src/consul_proxy.app.src +++ b/apps/consul_proxy/src/consul_proxy.app.src @@ -1,6 +1,6 @@ {application, consul_proxy, [ {description, "Proxy for docker swarm using consul and vegur"}, - {vsn, "0.5.1"}, + {vsn, "0.5.2"}, {registered, []}, {mod, {consul_proxy_app, []}}, {applications, [ diff --git a/apps/consul_proxy/src/consul_proxy_middleware_hijack.erl b/apps/consul_proxy/src/consul_proxy_middleware_hijack.erl index 3bc993e4888ad94a0b85ce3f534f12830210e802..2f5a93b48aa9fd2be4e54b6f0d01926fa1e72130 100644 --- a/apps/consul_proxy/src/consul_proxy_middleware_hijack.erl +++ b/apps/consul_proxy/src/consul_proxy_middleware_hijack.erl @@ -58,18 +58,23 @@ execute(Req, Env) -> case gen_server:call(?SERVER, {request, Req}) of {ignored, Req1} -> {ok, Req1, Env}; - {hijacked, <<"snoop">>, Req1} -> - {ok, Req1, Env}; - {hijacked, <<"hijack">>, Req1} -> + {hijacked, <<"snoop">>, Username, Req1} -> + Req2 = cowboyku_req:set_meta(hijack_mode, snoop, Req1), + Req3 = cowboyku_req:set_meta(hijack_user, Username, Req2), + {ok, Req3, Env}; + {hijacked, <<"hijack">>, Username, Req1} -> + Req2 = cowboyku_req:set_meta(hijack_mode, hijack, Req1), + Req3 = cowboyku_req:set_meta(hijack_user, Username, Req2), + Req4 = cowboyku_req:set_meta(status, hijacked, Req3), receive #{<<"status">> := Status, <<"headers">> := Headers, <<"body">> := Body} -> - {ok, Req2} = cowboyku_req:reply(Status, maps:to_list(Headers), Body, Req1), - {halt, Req2}; + {ok, Req5} = cowboyku_req:reply(Status, maps:to_list(Headers), Body, Req4), + {halt, Req5}; #{<<"error">> := Reason} -> - {ok, Req2} = cowboyku_req:reply(500, [], Reason, Req1), - {halt, Req2}; + {ok, Req5} = cowboyku_req:reply(500, [], Reason, Req4), + {halt, Req5}; _ -> - {ok, Req1, Env} + {ok, Req4, Env} end end. @@ -138,14 +143,14 @@ handle_call({socket_recv, Terms = #{<<"action">> := <<"login">>}, SocketState}, end end; -handle_call({socket_recv, Terms = #{<<"action">> := <<"bind">>}, SocketState = #socket_state{domains = Domains}}, _From, State) -> +handle_call({socket_recv, Terms = #{<<"action">> := <<"bind">>}, SocketState = #socket_state{username = Username, domains = Domains}}, _From, State) -> #{<<"host">> := Host, <<"path">> := Path, <<"mode">> := Mode} = Terms, #socket_state{socket = Socket, transport = Transport} = SocketState, case host_matches(Host, Domains) of true -> case re:compile(Path) of {ok, MP} -> - ets:insert(State#state.domain_tab, {Host, Mode, MP, Socket, Transport}), + ets:insert(State#state.domain_tab, {Host, Mode, Username, MP, Socket, Transport}), send(SocketState, Terms), lager:notice("~s/~s ~s by ~s on ~p", [Host, Path, Mode, SocketState#socket_state.username, Socket]), {reply, SocketState#socket_state{client_state = bound}, State}; @@ -183,7 +188,7 @@ handle_cast({socket_open, Socket, Transport}, State) -> {noreply, State}; handle_cast({socket_close, Socket}, State = #state{domain_tab = Tab}) -> - ets:match_delete(Tab, {'_', '_', '_', Socket, '_'}), + ets:match_delete(Tab, {'_', '_', '_', '_', Socket, '_'}), lager:notice("Socket closed: ~p", [Socket]), {noreply, State}; @@ -242,7 +247,7 @@ parse_users([User | Users], Parsed) -> hijack([], Req, _From) -> {ignored, Req}; -hijack([{_Host, Mode, RE, Socket, Transport} | Patterns], Req, From) -> +hijack([{_Host, Mode, Username, RE, Socket, Transport} | Patterns], Req, From) -> {Path, Req1} = cowboyku_req:path(Req), case re:run(Path, RE) of nomatch -> @@ -252,7 +257,7 @@ hijack([{_Host, Mode, RE, Socket, Transport} | Patterns], Req, From) -> {Map, Req2} = request_to_map(Req1), case Transport:send(Socket, msgpack:pack(Map#{<<"from">> => B64Pid})) of ok -> - {hijacked, Mode, Req2}; + {hijacked, Mode, Username, Req2}; {error, closed} -> lager:warning("Stale ~p socket: ~p", [Transport, Socket]), gen_server:cast(?SERVER, {socket_close, Socket}), diff --git a/apps/consul_proxy/src/consul_proxy_request_formatter.erl b/apps/consul_proxy/src/consul_proxy_request_formatter.erl index 5303dba557a62cd76e23944c3015a1ec4cde76a8..bf34296db76581fbd5ffff1655ea6c6e5f95e1a5 100644 --- a/apps/consul_proxy/src/consul_proxy_request_formatter.erl +++ b/apps/consul_proxy/src/consul_proxy_request_formatter.erl @@ -35,6 +35,33 @@ request_to_map(Req) -> {Cookies, _} = cowboyku_req:cookies(Req), {ServiceId, ServiceAddr, ServicePort} = service(Req), DomainGroup = meta(domain_group, Req, []), + Service = case cowboyku_req:meta(hijack_mode, Req) of + {undefined, _} -> + #{ + <<"address">> => list_to_binary(inet_parse:ntoa(ServiceAddr)), + <<"port">> => ServicePort, + <<"group_size">> => length(DomainGroup) + }; + {hijack, _} -> + {User, _} = cowboyku_req:meta(hijack_user, Req), + #{ + <<"hijack">> => #{ + <<"mode">> => <<"hijack">>, + <<"user">> => User + } + }; + {snoop, _} -> + {User, _} = cowboyku_req:meta(hijack_user, Req), + #{ + <<"address">> => list_to_binary(inet_parse:ntoa(ServiceAddr)), + <<"port">> => ServicePort, + <<"group_size">> => length(DomainGroup), + <<"hijack">> => #{ + <<"mode">> => <<"snoop">>, + <<"user">> => User + } + } + end, #{ <<"status">> => atom_to_binary(meta(status, Req, unknown), utf8), <<"request">> => #{ @@ -56,11 +83,7 @@ request_to_map(Req) -> <<"headers">> => maps:from_list(meta(response_headers, Req, [])), <<"bytes">> => meta(bytes_recv, Req, 0) }, - <<"service">> => maps:merge(service_id_fields(ServiceId), #{ - <<"address">> => list_to_binary(inet_parse:ntoa(ServiceAddr)), - <<"port">> => ServicePort, - <<"group_size">> => length(DomainGroup) - }) + <<"service">> => maps:merge(service_id_fields(ServiceId), Service) }. -spec metrics(Req :: req()) -> map(). diff --git a/apps/consul_proxy/src/consul_proxy_router.erl b/apps/consul_proxy/src/consul_proxy_router.erl index 6ce1bba92c64b6986fd40e505a1382a7d4a4cf42..25395655498df67776a74dcc8aa3d392a569fb96 100644 --- a/apps/consul_proxy/src/consul_proxy_router.erl +++ b/apps/consul_proxy/src/consul_proxy_router.erl @@ -66,7 +66,12 @@ additional_headers(downstream, _Log, _Upstream, HandlerState = #state{headers = {proplists:get_value(<<"Downstream">>, Headers, []), HandlerState}. terminate(_Reason, Upstream, _HandlerState) -> - consul_proxy_loadbalancer:analyze(Upstream), + case cowboyku_req:meta(hijack_mode, Upstream) of + {undefined, _} -> + consul_proxy_loadbalancer:analyze(Upstream); + _ -> + ok + end, request_log:info([Upstream]). %%%=================================================================== diff --git a/rebar.config b/rebar.config index 9efd372c34934779794f726cfc7105f5d95553d3..68ba2db877fdaed28d1a280c0bce4eecc5db3ec7 100644 --- a/rebar.config +++ b/rebar.config @@ -18,7 +18,7 @@ ]}. {relx, [ - {release, {consul_proxy, "0.5.1"}, [consul_proxy]}, {sys_config, "./config/sys.config"}, + {release, {consul_proxy, "0.5.2"}, [consul_proxy]}, {sys_config, "./config/sys.config"}, {vm_args, "./config/vm.args"}, {dev_mode, true}, {include_erts, false},