From cc94b1c4e24883d10e891e600e6ee162e3dda3cc Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Tue, 3 Dec 2019 12:09:18 -0500 Subject: [PATCH] Initial migration from internal repositories. --- LICENSE | 201 ++ README.md | 298 ++- fabric/controller/config.go | 250 +++ fabric/controller/controller.go | 168 ++ fabric/controller/db/db.go | 70 + fabric/controller/handler_ctrl/accept.go | 90 + fabric/controller/handler_ctrl/bind.go | 62 + .../handler_ctrl/bind_service_request.go | 74 + fabric/controller/handler_ctrl/close.go | 51 + fabric/controller/handler_ctrl/connect.go | 74 + fabric/controller/handler_ctrl/fault.go | 76 + fabric/controller/handler_ctrl/inspect.go | 77 + fabric/controller/handler_ctrl/link.go | 54 + fabric/controller/handler_ctrl/metrics.go | 47 + .../handler_ctrl/session_request.go | 83 + fabric/controller/handler_mgmt/accept.go | 54 + fabric/controller/handler_mgmt/bind.go | 80 + fabric/controller/handler_mgmt/close.go | 35 + fabric/controller/handler_mgmt/connect.go | 58 + .../controller/handler_mgmt/create_router.go | 54 + .../controller/handler_mgmt/create_service.go | 59 + fabric/controller/handler_mgmt/get_service.go | 68 + fabric/controller/handler_mgmt/inspect.go | 196 ++ fabric/controller/handler_mgmt/list_links.go | 75 + .../controller/handler_mgmt/list_routers.go | 79 + .../controller/handler_mgmt/list_services.go | 72 + .../controller/handler_mgmt/list_sessions.go | 81 + .../controller/handler_mgmt/remove_router.go | 58 + .../controller/handler_mgmt/remove_service.go | 54 + .../controller/handler_mgmt/remove_session.go | 53 + .../controller/handler_mgmt/set_link_cost.go | 57 + .../controller/handler_mgmt/set_link_down.go | 57 + .../controller/handler_mgmt/stream_metrics.go | 235 ++ .../handler_mgmt/stream_sessions.go | 115 + .../handler_mgmt/stream_toggle_pipe_traces.go | 171 ++ .../controller/handler_mgmt/stream_traces.go | 102 + fabric/controller/network/assembly.go | 74 + fabric/controller/network/circuit.go | 155 ++ fabric/controller/network/circuit_test.go | 161 ++ fabric/controller/network/handler.go | 22 + fabric/controller/network/link.go | 90 + fabric/controller/network/link_controller.go | 365 ++++ .../network/link_controller_test.go | 73 + fabric/controller/network/network.go | 637 ++++++ fabric/controller/network/options.go | 75 + fabric/controller/network/path.go | 105 + fabric/controller/network/router.go | 89 + fabric/controller/network/router_store.go | 142 ++ fabric/controller/network/service.go | 91 + fabric/controller/network/service_store.go | 152 ++ fabric/controller/network/session.go | 88 + .../controller/network/session_lifecycle.go | 165 ++ fabric/controller/network/smart.go | 89 + fabric/ctrl_msg/messages.go | 38 + fabric/doc/p12_smart_routing.md | 52 + fabric/etc/001.yml | 56 + fabric/etc/002.yml | 21 + fabric/etc/003.yml | 34 + fabric/etc/004.yml | 25 + fabric/etc/ca/certs/ca.cert.pem | 35 + fabric/etc/ca/index.txt | 1 + fabric/etc/ca/index.txt.attr | 1 + fabric/etc/ca/index.txt.old | 0 .../ca/intermediate/certs/001-client.cert.pem | 28 + .../ca/intermediate/certs/001-server.cert.pem | 28 + .../ca/intermediate/certs/002-client.cert.pem | 28 + .../ca/intermediate/certs/002-server.cert.pem | 28 + .../ca/intermediate/certs/003-client.cert.pem | 28 + .../ca/intermediate/certs/003-server.cert.pem | 28 + .../ca/intermediate/certs/004-client.cert.pem | 28 + .../ca/intermediate/certs/004-server.cert.pem | 28 + .../ca/intermediate/certs/ca-chain.cert.pem | 70 + .../intermediate/certs/ctrl-client.cert.pem | 28 + .../intermediate/certs/ctrl-server.cert.pem | 28 + .../certs/dotzeet-client.cert.pem | 28 + .../certs/dotzeet-server.cert.pem | 28 + .../intermediate/certs/intermediate.cert.pem | 35 + .../ca/intermediate/certs/mgmt-gw.cert.pem | 28 + fabric/etc/ca/intermediate/crlnumber | 1 + .../ca/intermediate/csr/001-client.csr.pem | 19 + .../ca/intermediate/csr/001-server.csr.pem | 19 + .../ca/intermediate/csr/002-client.csr.pem | 19 + .../ca/intermediate/csr/002-server.csr.pem | 19 + .../ca/intermediate/csr/003-client.csr.pem | 19 + .../ca/intermediate/csr/003-server.csr.pem | 19 + .../ca/intermediate/csr/004-client.csr.pem | 19 + .../ca/intermediate/csr/004-server.csr.pem | 19 + .../ca/intermediate/csr/ctrl-client.csr.pem | 19 + .../ca/intermediate/csr/ctrl-server.csr.pem | 19 + .../intermediate/csr/dotzeet-client.csr.pem | 19 + .../intermediate/csr/dotzeet-server.csr.pem | 19 + .../ca/intermediate/csr/intermediate.csr.pem | 30 + .../etc/ca/intermediate/csr/mgmt-gw.csr.pem | 19 + fabric/etc/ca/intermediate/index.txt | 19 + fabric/etc/ca/intermediate/index.txt.attr | 1 + fabric/etc/ca/intermediate/index.txt.attr.old | 1 + fabric/etc/ca/intermediate/index.txt.old | 18 + fabric/etc/ca/intermediate/newcerts/1000.pem | 28 + fabric/etc/ca/intermediate/newcerts/1001.pem | 28 + fabric/etc/ca/intermediate/newcerts/1002.pem | 28 + fabric/etc/ca/intermediate/newcerts/1003.pem | 28 + fabric/etc/ca/intermediate/newcerts/1004.pem | 28 + fabric/etc/ca/intermediate/newcerts/1005.pem | 28 + fabric/etc/ca/intermediate/newcerts/1006.pem | 28 + fabric/etc/ca/intermediate/newcerts/1007.pem | 28 + fabric/etc/ca/intermediate/newcerts/1008.pem | 28 + fabric/etc/ca/intermediate/newcerts/1009.pem | 28 + fabric/etc/ca/intermediate/newcerts/100A.pem | 28 + fabric/etc/ca/intermediate/newcerts/100B.pem | 28 + fabric/etc/ca/intermediate/newcerts/100C.pem | 28 + fabric/etc/ca/intermediate/newcerts/100D.pem | 28 + fabric/etc/ca/intermediate/newcerts/100E.pem | 28 + fabric/etc/ca/intermediate/newcerts/100F.pem | 28 + fabric/etc/ca/intermediate/newcerts/1010.pem | 28 + fabric/etc/ca/intermediate/newcerts/1011.pem | 28 + fabric/etc/ca/intermediate/newcerts/1012.pem | 28 + fabric/etc/ca/intermediate/openssl.cnf | 144 ++ .../etc/ca/intermediate/private/001.key.pem | 27 + .../etc/ca/intermediate/private/002.key.pem | 27 + .../etc/ca/intermediate/private/003.key.pem | 27 + .../etc/ca/intermediate/private/004.key.pem | 27 + .../etc/ca/intermediate/private/ctrl.key.pem | 27 + .../ca/intermediate/private/dotzeet.key.pem | 27 + .../private/intermediate.key.decrypted.pem | 51 + .../intermediate/private/intermediate.key.pem | 54 + .../ca/intermediate/private/mgmt-gw.key.pem | 27 + fabric/etc/ca/intermediate/serial | 1 + fabric/etc/ca/intermediate/serial.old | 1 + fabric/etc/ca/newcerts/1000.pem | 35 + fabric/etc/ca/openssl.cnf | 131 ++ fabric/etc/ca/private/ca.key.pem | 54 + fabric/etc/ca/serial | 1 + fabric/etc/ca/serial.old | 1 + fabric/etc/ctrl.with.edge.yml | 79 + fabric/etc/ctrl.yml | 40 + fabric/etc/edge.router.yml | 83 + fabric/etc/gw.yml | 10 + fabric/etc/loop2/10-ambient.loop2.yml | 30 + fabric/etc/loop2/1k-stress.loop2.yml | 30 + fabric/etc/loop2/256-medium.loop2.yml | 30 + fabric/etc/loop2/8k-chatter.loop2.yml | 17 + fabric/etc/loop2/example.loop2.yml | 30 + fabric/etc/loop2/failover.loop2.yml | 16 + fabric/metrics/channel_reporter.go | 54 + fabric/metrics/config.go | 53 + fabric/metrics/event_controller.go | 126 ++ fabric/metrics/histogram.go | 35 + fabric/metrics/influxdb_reporter.go | 232 ++ fabric/metrics/interval_counter.go | 178 ++ fabric/metrics/interval_counter_test.go | 176 ++ fabric/metrics/latency.go | 80 + fabric/metrics/meter.go | 35 + fabric/metrics/metrics_msg_builder.go | 117 + fabric/metrics/peekhandler.go | 237 +++ fabric/metrics/registry.go | 203 ++ fabric/pb/ctrl_pb/ctrl.pb.go | 1303 ++++++++++++ fabric/pb/ctrl_pb/ctrl.proto | 156 ++ fabric/pb/ctrl_pb/decoder.go | 230 ++ fabric/pb/ctrl_pb/inspect.go | 33 + fabric/pb/mgmt_pb/decoder.go | 323 +++ fabric/pb/mgmt_pb/mgmt.pb.go | 1892 +++++++++++++++++ fabric/pb/mgmt_pb/mgmt.proto | 244 +++ fabric/router/config.go | 283 +++ fabric/router/forwarder/forwarder.go | 234 ++ fabric/router/forwarder/link.go | 46 + fabric/router/forwarder/options.go | 44 + fabric/router/forwarder/tables.go | 167 ++ fabric/router/handler_ctrl/bind.go | 76 + fabric/router/handler_ctrl/dial.go | 117 + fabric/router/handler_ctrl/inspect.go | 104 + fabric/router/handler_ctrl/route.go | 110 + fabric/router/handler_ctrl/start_xgress.go | 44 + .../router/handler_ctrl/toggle_pipe_traces.go | 99 + fabric/router/handler_ctrl/unroute.go | 47 + fabric/router/handler_link/accept.go | 80 + fabric/router/handler_link/ack.go | 50 + fabric/router/handler_link/bind.go | 50 + fabric/router/handler_link/close.go | 55 + fabric/router/handler_link/error.go | 52 + fabric/router/handler_link/payload.go | 57 + fabric/router/handler_xgress/bind.go | 54 + fabric/router/handler_xgress/close.go | 70 + fabric/router/handler_xgress/receive.go | 38 + fabric/router/monitor.go | 21 + fabric/router/monitor_darwin.go | 42 + fabric/router/monitor_linux.go | 42 + fabric/router/monitor_windows.go | 34 + fabric/router/router.go | 215 ++ fabric/trace/channel_peekhandler.go | 165 ++ fabric/trace/controller.go | 235 ++ fabric/trace/event_controller.go | 125 ++ fabric/trace/filter.go | 67 + fabric/trace/xgress_peekhandler.go | 110 + fabric/xctrl/ops.go | 59 + fabric/xctrl/xctrl.go | 30 + fabric/xctrl_example/example.go | 90 + fabric/xctrl_example/receive.go | 48 + fabric/xgress/ctrl.go | 25 + fabric/xgress/decoder.go | 86 + fabric/xgress/messages.go | 249 +++ fabric/xgress/messages_test.go | 108 + fabric/xgress/options.go | 64 + fabric/xgress/payload_buffer.go | 310 +++ fabric/xgress/registry.go | 69 + fabric/xgress/request.go | 288 +++ fabric/xgress/transmit_buffer.go | 61 + fabric/xgress/xgress.go | 361 ++++ fabric/xgress_proxy/connection.go | 41 + fabric/xgress_proxy/factory.go | 49 + fabric/xgress_proxy/listener.go | 76 + fabric/xgress_transport/client.go | 50 + fabric/xgress_transport/connection.go | 43 + fabric/xgress_transport/dialer.go | 57 + fabric/xgress_transport/factory.go | 43 + fabric/xgress_transport/listener.go | 88 + fabric/xgress_udp/address.go | 64 + fabric/xgress_udp/connection.go | 43 + fabric/xgress_udp/dialer.go | 62 + fabric/xgress_udp/factory.go | 45 + fabric/xgress_udp/listener.go | 283 +++ fabric/xmgmt/xmgmt.go | 29 + 221 files changed, 20126 insertions(+), 4 deletions(-) create mode 100644 LICENSE create mode 100644 fabric/controller/config.go create mode 100644 fabric/controller/controller.go create mode 100644 fabric/controller/db/db.go create mode 100644 fabric/controller/handler_ctrl/accept.go create mode 100644 fabric/controller/handler_ctrl/bind.go create mode 100644 fabric/controller/handler_ctrl/bind_service_request.go create mode 100644 fabric/controller/handler_ctrl/close.go create mode 100644 fabric/controller/handler_ctrl/connect.go create mode 100644 fabric/controller/handler_ctrl/fault.go create mode 100644 fabric/controller/handler_ctrl/inspect.go create mode 100644 fabric/controller/handler_ctrl/link.go create mode 100644 fabric/controller/handler_ctrl/metrics.go create mode 100644 fabric/controller/handler_ctrl/session_request.go create mode 100644 fabric/controller/handler_mgmt/accept.go create mode 100644 fabric/controller/handler_mgmt/bind.go create mode 100644 fabric/controller/handler_mgmt/close.go create mode 100644 fabric/controller/handler_mgmt/connect.go create mode 100644 fabric/controller/handler_mgmt/create_router.go create mode 100644 fabric/controller/handler_mgmt/create_service.go create mode 100644 fabric/controller/handler_mgmt/get_service.go create mode 100644 fabric/controller/handler_mgmt/inspect.go create mode 100644 fabric/controller/handler_mgmt/list_links.go create mode 100644 fabric/controller/handler_mgmt/list_routers.go create mode 100644 fabric/controller/handler_mgmt/list_services.go create mode 100644 fabric/controller/handler_mgmt/list_sessions.go create mode 100644 fabric/controller/handler_mgmt/remove_router.go create mode 100644 fabric/controller/handler_mgmt/remove_service.go create mode 100644 fabric/controller/handler_mgmt/remove_session.go create mode 100644 fabric/controller/handler_mgmt/set_link_cost.go create mode 100644 fabric/controller/handler_mgmt/set_link_down.go create mode 100644 fabric/controller/handler_mgmt/stream_metrics.go create mode 100644 fabric/controller/handler_mgmt/stream_sessions.go create mode 100644 fabric/controller/handler_mgmt/stream_toggle_pipe_traces.go create mode 100644 fabric/controller/handler_mgmt/stream_traces.go create mode 100644 fabric/controller/network/assembly.go create mode 100644 fabric/controller/network/circuit.go create mode 100644 fabric/controller/network/circuit_test.go create mode 100644 fabric/controller/network/handler.go create mode 100644 fabric/controller/network/link.go create mode 100644 fabric/controller/network/link_controller.go create mode 100644 fabric/controller/network/link_controller_test.go create mode 100644 fabric/controller/network/network.go create mode 100644 fabric/controller/network/options.go create mode 100644 fabric/controller/network/path.go create mode 100644 fabric/controller/network/router.go create mode 100644 fabric/controller/network/router_store.go create mode 100644 fabric/controller/network/service.go create mode 100644 fabric/controller/network/service_store.go create mode 100644 fabric/controller/network/session.go create mode 100644 fabric/controller/network/session_lifecycle.go create mode 100644 fabric/controller/network/smart.go create mode 100644 fabric/ctrl_msg/messages.go create mode 100644 fabric/doc/p12_smart_routing.md create mode 100644 fabric/etc/001.yml create mode 100644 fabric/etc/002.yml create mode 100644 fabric/etc/003.yml create mode 100644 fabric/etc/004.yml create mode 100644 fabric/etc/ca/certs/ca.cert.pem create mode 100644 fabric/etc/ca/index.txt create mode 100644 fabric/etc/ca/index.txt.attr create mode 100644 fabric/etc/ca/index.txt.old create mode 100644 fabric/etc/ca/intermediate/certs/001-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/001-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/002-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/002-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/003-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/003-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/004-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/004-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/ca-chain.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/dotzeet-client.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/dotzeet-server.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/intermediate.cert.pem create mode 100644 fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem create mode 100644 fabric/etc/ca/intermediate/crlnumber create mode 100644 fabric/etc/ca/intermediate/csr/001-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/001-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/002-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/002-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/003-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/003-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/004-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/004-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/ctrl-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/ctrl-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/dotzeet-client.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/dotzeet-server.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/intermediate.csr.pem create mode 100644 fabric/etc/ca/intermediate/csr/mgmt-gw.csr.pem create mode 100644 fabric/etc/ca/intermediate/index.txt create mode 100644 fabric/etc/ca/intermediate/index.txt.attr create mode 100644 fabric/etc/ca/intermediate/index.txt.attr.old create mode 100644 fabric/etc/ca/intermediate/index.txt.old create mode 100644 fabric/etc/ca/intermediate/newcerts/1000.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1001.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1002.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1003.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1004.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1005.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1006.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1007.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1008.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1009.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100A.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100B.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100C.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100D.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100E.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/100F.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1010.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1011.pem create mode 100644 fabric/etc/ca/intermediate/newcerts/1012.pem create mode 100644 fabric/etc/ca/intermediate/openssl.cnf create mode 100644 fabric/etc/ca/intermediate/private/001.key.pem create mode 100644 fabric/etc/ca/intermediate/private/002.key.pem create mode 100644 fabric/etc/ca/intermediate/private/003.key.pem create mode 100644 fabric/etc/ca/intermediate/private/004.key.pem create mode 100644 fabric/etc/ca/intermediate/private/ctrl.key.pem create mode 100644 fabric/etc/ca/intermediate/private/dotzeet.key.pem create mode 100644 fabric/etc/ca/intermediate/private/intermediate.key.decrypted.pem create mode 100644 fabric/etc/ca/intermediate/private/intermediate.key.pem create mode 100644 fabric/etc/ca/intermediate/private/mgmt-gw.key.pem create mode 100644 fabric/etc/ca/intermediate/serial create mode 100644 fabric/etc/ca/intermediate/serial.old create mode 100644 fabric/etc/ca/newcerts/1000.pem create mode 100644 fabric/etc/ca/openssl.cnf create mode 100644 fabric/etc/ca/private/ca.key.pem create mode 100644 fabric/etc/ca/serial create mode 100644 fabric/etc/ca/serial.old create mode 100644 fabric/etc/ctrl.with.edge.yml create mode 100644 fabric/etc/ctrl.yml create mode 100644 fabric/etc/edge.router.yml create mode 100644 fabric/etc/gw.yml create mode 100644 fabric/etc/loop2/10-ambient.loop2.yml create mode 100644 fabric/etc/loop2/1k-stress.loop2.yml create mode 100644 fabric/etc/loop2/256-medium.loop2.yml create mode 100644 fabric/etc/loop2/8k-chatter.loop2.yml create mode 100644 fabric/etc/loop2/example.loop2.yml create mode 100644 fabric/etc/loop2/failover.loop2.yml create mode 100644 fabric/metrics/channel_reporter.go create mode 100644 fabric/metrics/config.go create mode 100644 fabric/metrics/event_controller.go create mode 100644 fabric/metrics/histogram.go create mode 100644 fabric/metrics/influxdb_reporter.go create mode 100644 fabric/metrics/interval_counter.go create mode 100644 fabric/metrics/interval_counter_test.go create mode 100644 fabric/metrics/latency.go create mode 100644 fabric/metrics/meter.go create mode 100644 fabric/metrics/metrics_msg_builder.go create mode 100644 fabric/metrics/peekhandler.go create mode 100644 fabric/metrics/registry.go create mode 100644 fabric/pb/ctrl_pb/ctrl.pb.go create mode 100644 fabric/pb/ctrl_pb/ctrl.proto create mode 100644 fabric/pb/ctrl_pb/decoder.go create mode 100644 fabric/pb/ctrl_pb/inspect.go create mode 100644 fabric/pb/mgmt_pb/decoder.go create mode 100644 fabric/pb/mgmt_pb/mgmt.pb.go create mode 100644 fabric/pb/mgmt_pb/mgmt.proto create mode 100644 fabric/router/config.go create mode 100644 fabric/router/forwarder/forwarder.go create mode 100644 fabric/router/forwarder/link.go create mode 100644 fabric/router/forwarder/options.go create mode 100644 fabric/router/forwarder/tables.go create mode 100644 fabric/router/handler_ctrl/bind.go create mode 100644 fabric/router/handler_ctrl/dial.go create mode 100644 fabric/router/handler_ctrl/inspect.go create mode 100644 fabric/router/handler_ctrl/route.go create mode 100644 fabric/router/handler_ctrl/start_xgress.go create mode 100644 fabric/router/handler_ctrl/toggle_pipe_traces.go create mode 100644 fabric/router/handler_ctrl/unroute.go create mode 100644 fabric/router/handler_link/accept.go create mode 100644 fabric/router/handler_link/ack.go create mode 100644 fabric/router/handler_link/bind.go create mode 100644 fabric/router/handler_link/close.go create mode 100644 fabric/router/handler_link/error.go create mode 100644 fabric/router/handler_link/payload.go create mode 100644 fabric/router/handler_xgress/bind.go create mode 100644 fabric/router/handler_xgress/close.go create mode 100644 fabric/router/handler_xgress/receive.go create mode 100644 fabric/router/monitor.go create mode 100644 fabric/router/monitor_darwin.go create mode 100644 fabric/router/monitor_linux.go create mode 100644 fabric/router/monitor_windows.go create mode 100644 fabric/router/router.go create mode 100644 fabric/trace/channel_peekhandler.go create mode 100644 fabric/trace/controller.go create mode 100644 fabric/trace/event_controller.go create mode 100644 fabric/trace/filter.go create mode 100644 fabric/trace/xgress_peekhandler.go create mode 100644 fabric/xctrl/ops.go create mode 100644 fabric/xctrl/xctrl.go create mode 100644 fabric/xctrl_example/example.go create mode 100644 fabric/xctrl_example/receive.go create mode 100644 fabric/xgress/ctrl.go create mode 100644 fabric/xgress/decoder.go create mode 100644 fabric/xgress/messages.go create mode 100644 fabric/xgress/messages_test.go create mode 100644 fabric/xgress/options.go create mode 100644 fabric/xgress/payload_buffer.go create mode 100644 fabric/xgress/registry.go create mode 100644 fabric/xgress/request.go create mode 100644 fabric/xgress/transmit_buffer.go create mode 100644 fabric/xgress/xgress.go create mode 100644 fabric/xgress_proxy/connection.go create mode 100644 fabric/xgress_proxy/factory.go create mode 100644 fabric/xgress_proxy/listener.go create mode 100644 fabric/xgress_transport/client.go create mode 100644 fabric/xgress_transport/connection.go create mode 100644 fabric/xgress_transport/dialer.go create mode 100644 fabric/xgress_transport/factory.go create mode 100644 fabric/xgress_transport/listener.go create mode 100644 fabric/xgress_udp/address.go create mode 100644 fabric/xgress_udp/connection.go create mode 100644 fabric/xgress_udp/dialer.go create mode 100644 fabric/xgress_udp/factory.go create mode 100644 fabric/xgress_udp/listener.go create mode 100644 fabric/xmgmt/xmgmt.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 188592c84..362b39a78 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,297 @@ -# Ziti Fabric +**This documentation requires revision after the migration to GitHub is complete.** -Ziti is a modern, programmable network overlay with associated edge components, for application-embedded, zero trust network connectivity, written by developers for developers. Ziti allows developers to take control of networking while with secure connectivity and advanced security concepts such as Zero Trust. +# Ziti Fabric Layer -The Ziti Fabric represents the geo-scale network overlay, and core network programming model for the Ziti ecosystem. +The Ziti Fabric is a long-haul transport fabric for the Ziti ecosystem. -Currently working through migrating our internal repositories over to GitHub. Stay tuned. \ No newline at end of file +## Creating a Development Workspace + +If you're going to be working on the Ziti fabric, or just want to track the latest development changes, you'll need a development workspace. + +First, install the golang environment for your platform. Visit http://golang.org to download your installer. + +As of this update, we're currently using version `1.13` of golang. + +Make sure that `go` is in your path: + + $ go version + go version go1.13.1 linux/amd64 + +You'll need to create a `GOPATH` for Ziti. I like to put mine in `~/Repos/nf/ziti`, but you can root it wherever you'd like. I'd suggest you call it `ziti`. + +Essentially: + +* `mkdir ziti` +* `cd ziti` +* `export GOPATH=$(pwd)` + +When you've got your `GOPATH` ready, clone the repository. + +* Clone this repository into `$GOPATH/src/bitbucket.org/netfoundry/ziti` + * `mkdir -p $GOPATH/src/bitbucket.org/netfoundry` + * `cd $GOPATH/src/bitbucket.org/netfoundry` + * `git clone git@bitbucket.org:netfoundry/ziti` + +Build the tree: + + $ go install ./... + +The binaries will be placed in `$GOPATH/bin`. + +The development configuration files live in `$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc`, and contain relative paths, which expect the executables to be started from `$GOPATH`. + + $ cd $GOPATH + $ mkdir -p db + $ bin/ziti-controller run src/github.com/netfoundry/ziti-fabric/fabric/etc/ctrl.yml + +## Launching A Simple Environment + +You'll want to open a number of terminal windows. All commands are executed relative to `$GOPATH` (shell PWD is `$GOPATH`). + +### Launch The Controller + +`$ bin/ziti-controller run src/github.com/netfoundry/ziti-fabric/fabric/etc/ctrl.yml` + +### Configure Dotzeet + +In order to use the `ziti-fabric` tool, you'll need a working identity configuration in your home directory. Create the file `~/.ziti/identities.yml` containing the following. Substitute your concrete `$GOPATH` for the actual value of your `$GOPATH` in this file: + +``` +default: + caCert: "$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem" + cert: "$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/dotzeet-client.cert.pem" + serverCert: "$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/dotzeet-server.cert.pem" + key: "$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/private/dotzeet.key.pem" + endpoint: tls:127.0.0.1:10000 +``` + +Where, `"caCert": "$GOPATH/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem"` becomes `"caCert": "/home/michael/Repos/nf/ziti/src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem"`. + +The `endpoint:` specification should point at the `mgmt` listener address for your `ziti-controller`. + +### Enroll Routers + +With your controller running, use the `ziti-fabric` tool to enroll routers: + + $ bin/ziti-fabric create router src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/001-client.cert.pem + $ bin/ziti-fabric create router src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/002-client.cert.pem + $ bin/ziti-fabric create router src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/003-client.cert.pem + $ bin/ziti-fabric create router src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/004-client.cert.pem + +### Start Routers + +With your controller running, you can now start routers to begin building your mesh: + +`$ bin/ziti-router run src/github.com/netfoundry/ziti-fabric/fabric/etc/001.yml` + +There are 4 router configurations provided (001, 002, 003, 004). + +Start routers 001, 002, and 003. + +The configuration provided in the tree assembles a "diamond" shaped mesh, where router `001` is intended to initiate +(ingress) sessions, and router `003` is intended to terminate (egress) sessions. With smart routing and dynamic healing +in play, traffic can flow between router `001` and router `003` over either router `002` or `004`. + +### Create a Google Service + +Create a service to access `google.com`: + +`$ bin/ziti-fabric create service google tcp:google.com:80 003` + +### Access the Google Service + +Access the google service using `ziti-fabric`: + +`$ bin/ziti-fabric-test http http://google --host www.google.com` + +You should see HTTP output from the google website. + +## Using The Fabric InfluxDB Metrics Reporter + +First you'll want to launch an InfluxDB docker container like this: + + $ docker run --name influxdb -d -p 8086:8086 -v /opt/influxdb:/var/lib/influxdb influxdb + +The directory `/opt/influxdb` should be changed to wherever you would like InfluxDB to persist its data. + +Next, open an `influx` cli connection: + + $ docker exec -it influxdb influx + Connected to http://localhost:8086 version 1.7.7 + InfluxDB shell version: 1.7.7 + > + +Then create the `ziti` database: + + > create database ziti + > + +Exit the `influx` cli. InfluxDB is ready to go. + +Make sure you uncomment the `metrics` section in the `fabric/etc/ctrl.yml`: + + metrics: + influxdb: + enabled: true + url: http://localhost:8086 + database: ziti + +Restart your controller and metrics should begin flowing into InfluxDB. You can verify like this: + + $ docker exec -it influxdb influx + Connected to http://localhost:8086 version 1.7.7 + InfluxDB shell version: 1.7.7 + > use ziti + Using database ziti + > show series + key + --- + egress.rx.bytesrate,source=001 + egress.rx.bytesrate,source=002 + egress.rx.bytesrate,source=003 + ----8<---- + link.OY8P.tx.msgsize,source=002 + link.OY8P.tx.msgsize,source=003 + link.yMey.latency,source=001 + link.yMey.latency,source=002 + link.yMey.rx.bytesrate,source=001 + link.yMey.rx.bytesrate,source=002 + link.yMey.rx.msgrate,source=001 + link.yMey.rx.msgrate,source=002 + link.yMey.rx.msgsize,source=001 + link.yMey.rx.msgsize,source=002 + link.yMey.tx.bytesrate,source=001 + link.yMey.tx.bytesrate,source=002 + link.yMey.tx.msgrate,source=001 + link.yMey.tx.msgrate,source=002 + link.yMey.tx.msgsize,source=001 + link.yMey.tx.msgsize,source=002 + > select * from "link.yMey.latency" + name: link.yMey.latency + time count max mean min p50 p75 p95 p99 p999 p9999 source stddev variance + ---- ----- --- ---- --- --- --- --- --- ---- ----- ------ ------ -------- + 1563471804584021939 1 615541 615541 615541 615541 615541 615541 615541 615541 615541 001 0 0 + 1563471807396555092 1 549054 549054 549054 549054 549054 549054 549054 549054 549054 002 0 0 + 1563471819583707653 2 630068 622804.5 615541 622804.5 630068 630068 630068 630068 630068 001 7263.5 52758432.25 + 1563471822396356386 2 549054 506257 463460 506257 549054 549054 549054 549054 549054 002 42797 1831583209 + > select * from "link.yMey.latency" + name: link.yMey.latency + time count max mean min p50 p75 p95 p99 p999 p9999 source stddev variance + ---- ----- --- ---- --- --- --- --- --- ---- ----- ------ ------ -------- + 1563471804584021939 1 615541 615541 615541 615541 615541 615541 615541 615541 615541 001 0 0 + 1563471807396555092 1 549054 549054 549054 549054 549054 549054 549054 549054 549054 002 0 0 + 1563471819583707653 2 630068 622804.5 615541 622804.5 630068 630068 630068 630068 630068 001 7263.5 52758432.25 + 1563471822396356386 2 549054 506257 463460 506257 549054 549054 549054 549054 549054 002 42797 1831583209 + 1563471834584197383 3 630068 555820 421851 615541 630068 630068 630068 630068 630068 001 94915.85098742289 9009018768.666666 + > + +## Using The Fabric (JSON) Gateway + +Launch the `ziti-fabric-gw` like this: + + $ bin/ziti-fabric-gw run src/github.com/netfoundry/ziti-fabric/fabric/etc/gw.yml + +Client access like this: + + $ cd ${GOPATH}/src/bitbucket.org/netfoundry/ziti + $ curl --cacert fabric/etc/ca/intermediate/certs/ca-chain.cert.pem --cert fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem --key fabric/etc/ca/intermediate/private/ctrl.key.pem https://127.0.0.1:10080/ctrl/services | jq + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 443 100 443 0 0 88600 0 --:--:-- --:--:-- --:--:-- 88600 + { + "data": [ + { + "id": "google", + "endpointAddress": "tls:www.google.com:443", + "egress": "003", + "binding": "" + }, + { + "id": "googles", + "endpointAddress": "tcp:www.google.com:443", + "egress": "003", + "binding": "" + }, + { + "id": "loop", + "endpointAddress": "tcp:127.0.0.1:8171", + "egress": "003", + "binding": "" + }, + { + "id": "loop-broken", + "endpointAddress": "tcp:127.0.0.1:8171", + "egress": "003", + "binding": "" + }, + { + "id": "quigley", + "endpointAddress": "tcp:one.quigley.com:80", + "egress": "003", + "binding": "" + } + ] + } + +To use `ziti-fabric-gw` with a plain HTTP listener (without TLS), comment out the `certPath` and `keyPath` lines in `gw.yml`: + + # Comment out the following lines to disable the TLS listener + #certPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem + #keyPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem + +And then the listener can be accessed with plain HTTP: + + $ curl http://127.0.0.1:10080/ctrl/services | jq + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 443 100 443 0 0 432k 0 --:--:-- --:--:-- --:--:-- 432k + { + "data": [ + { + "id": "google", + "binding": "", + "endpointAddress": "tls:www.google.com:443", + "egress": "003" + } + ] + } + + +## Generating Network Load Using loop2 + +In order to create interesting metrics, you'll need to create some network load. A simple tool for that is the `ziti-fabric-test loop2` tool. + +Create the `loop` service in the fabric (if it's not already there): + + $ bin/ziti-fabric create service loop tcp:127.0.0.1:8171 003 + +Launch a `loop2` listener (in $GOPATH): + + $ bin/ziti-fabric-test loop2 listener + +Launch a `loop2` dialer (begin generating load): + + $ bin/ziti-fabric-test loop2 dialer src/github.com/netfoundry/ziti-fabric/fabric/etc/loop2/10-ambient.loop2.yml + +Take a look at the various `loop2` scenario configurations in `fabric/etc/loop2` for examples of how to create a specific kind of workload. + +## Creating Keys and Certificates for Development + +This is not necessary if you are using the PKI infrastructure that is already configured in the development config files (above). + +This is only necessary if you want to generate your own PKI infrastructure for your own configuration. + + ziti pki create --pki-root=/home/plorenz/tmp/002 ca --ca-name=root-ca --ca-file=root-ca + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=root-ca intermediate + + ziti pki create key --pki-root /home/plorenz/tmp/002/ --ca-name=intermediate --key-file ctrl + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate server --server-file=ctrl-server --ip 127.0.0.1 --key-file ctrl + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate client --client-file=ctrl-client --key-file ctrl + + ziti pki create key --pki-root /home/plorenz/tmp/002/ --ca-name=intermediate --key-file dotzeet + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate server --server-file=dotzeet-server --ip 127.0.0.1 --key-file dotzeet + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate client --client-file=dotzeet-client --key-file dotzeet + + ziti pki create key --pki-root /home/plorenz/tmp/002/ --ca-name=intermediate --key-file 002 + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate server --server-file=002-server --ip 127.0.0.1 --key-file 002 --server-name 002 + ziti pki create --pki-root=/home/plorenz/tmp/002/ --ca-name=intermediate client --client-file=002-client --key-file 002 --client-name 002 diff --git a/fabric/controller/config.go b/fabric/controller/config.go new file mode 100644 index 000000000..93a96612a --- /dev/null +++ b/fabric/controller/config.go @@ -0,0 +1,250 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package controller + +import ( + "github.com/netfoundry/ziti-foundation/config" + "github.com/netfoundry/ziti-fabric/fabric/controller/db" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "bytes" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "gopkg.in/yaml.v2" + "io/ioutil" + "time" +) + +type Config struct { + Id *identity.TokenId + Network *network.Options + Db *db.Db + Trace struct { + Handler *channel2.TraceHandler + } + Profile struct { + Memory struct { + Path string + Interval time.Duration + } + CPU struct { + Path string + } + } + Ctrl struct { + Listener transport.Address + Options *channel2.Options + } + Mgmt struct { + Listener transport.Address + Options *channel2.Options + } + Metrics *metrics.Config + src map[interface{}]interface{} +} + +func (config *Config) Configure(sub config.Subconfig) error { + return sub.LoadConfig(config.src) +} + +func LoadConfig(path string) (*Config, error) { + cfgBytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + cfgmap := make(map[interface{}]interface{}) + if err = yaml.NewDecoder(bytes.NewReader(cfgBytes)).Decode(&cfgmap); err != nil { + return nil, err + } + config.InjectEnv(cfgmap) + if value, found := cfgmap["v"]; found { + if value.(int) != 3 { + panic("config version mismatch: see docs for information on config updates") + } + } else { + panic("no config version: see docs for information on config") + } + + identityConfig := identity.IdentityConfig{} + if value, found := cfgmap["identity"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["key"]; found { + identityConfig.Key = value.(string) + } + if value, found := submap["cert"]; found { + identityConfig.Cert = value.(string) + } + if value, found := submap["server_cert"]; found { + identityConfig.ServerCert = value.(string) + } + if value, found := submap["server_key"]; found { + identityConfig.ServerKey = value.(string) + } + if value, found := submap["ca"]; found { + identityConfig.CA = value.(string) + } + } + } + + config := &Config{ + Network: network.DefaultOptions(), + src: cfgmap, + } + + if id, err := identity.LoadIdentity(identityConfig); err != nil { + return nil, fmt.Errorf("unable to load identity (%s)", err) + } else { + config.Id = identity.NewIdentity(id) + } + + if value, found := cfgmap["network"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if options, err := network.LoadOptions(submap); err == nil { + config.Network = options + } else { + return nil, fmt.Errorf("invalid 'network' stanza (%s)", err) + } + } else { + pfxlog.Logger().Warn("invalid or empty 'network' stanza") + } + } + + if value, found := cfgmap["db"]; found { + str, err := db.Open(value.(string)) + if err != nil { + return nil, err + } + config.Db = str + } else { + panic("config must provide [db]") + } + + if value, found := cfgmap["trace"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["path"]; found { + handler, err := channel2.NewTraceHandler(value.(string), config.Id) + if err != nil { + return nil, err + } + handler.AddDecoder(&channel2.Decoder{}) + handler.AddDecoder(&ctrl_pb.Decoder{}) + handler.AddDecoder(&xgress.Decoder{}) + handler.AddDecoder(&mgmt_pb.Decoder{}) + config.Trace.Handler = handler + } + } + } + + if value, found := cfgmap["profile"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["memory"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["path"]; found { + config.Profile.Memory.Path = value.(string) + } + if value, found := submap["intervalMs"]; found { + config.Profile.Memory.Interval = time.Duration(value.(int)) * time.Millisecond + } else { + config.Profile.Memory.Interval = 15 * time.Second + } + } + } + if value, found := submap["cpu"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["path"]; found { + config.Profile.CPU.Path = value.(string) + } + } + } + } + } + + if value, found := cfgmap["ctrl"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["listener"]; found { + listener, err := transport.ParseAddress(value.(string)) + if err != nil { + return nil, err + } + config.Ctrl.Listener = listener + } else { + panic("config must provide [ctrl/listener]") + } + + config.Ctrl.Options = channel2.DefaultOptions() + if value, found := submap["options"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + config.Ctrl.Options = channel2.LoadOptions(submap) + } + } + + if config.Trace.Handler != nil { + config.Ctrl.Options.PeekHandlers = append(config.Ctrl.Options.PeekHandlers, config.Trace.Handler) + } + } else { + panic("config [ctrl] section in unexpected format") + } + } else { + panic("config must provide [ctrl]") + } + + if value, found := cfgmap["mgmt"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["listener"]; found { + listener, err := transport.ParseAddress(value.(string)) + if err != nil { + return nil, err + } + config.Mgmt.Listener = listener + } else { + panic("config must provide [mgmt/listener]") + } + + config.Mgmt.Options = channel2.DefaultOptions() + if value, found := submap["options"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + config.Mgmt.Options = channel2.LoadOptions(submap) + } + } + } else { + panic("config [mgmt] section in unexpected format") + } + } else { + panic("config must provide [mgmt]") + } + + if value, found := cfgmap["metrics"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if metricsCfg, err := metrics.LoadConfig(submap); err == nil { + config.Metrics = metricsCfg + } else { + return nil, fmt.Errorf("error loading metrics config (%s)", err) + } + } else { + pfxlog.Logger().Warn("invalid or empty [metrics] stanza") + } + } + + return config, nil +} diff --git a/fabric/controller/controller.go b/fabric/controller/controller.go new file mode 100644 index 000000000..54d661446 --- /dev/null +++ b/fabric/controller/controller.go @@ -0,0 +1,168 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package controller + +import ( + "github.com/netfoundry/ziti-fabric/fabric/controller/handler_ctrl" + "github.com/netfoundry/ziti-fabric/fabric/controller/handler_mgmt" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "github.com/netfoundry/ziti-fabric/fabric/xctrl_example" + "github.com/netfoundry/ziti-fabric/fabric/xmgmt" + "github.com/netfoundry/ziti-foundation/profiler" + "encoding/json" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" +) + +type Controller struct { + config *Config + network *network.Network + ctrlConnectHandler *handler_ctrl.ConnectHandler + mgmtConnectHandler *handler_mgmt.ConnectHandler + xctrls []xctrl.Xctrl + xmgmts []xmgmt.Xmgmt + + ctrlListener channel2.UnderlayListener + mgmtListener channel2.UnderlayListener +} + +func NewController(cfg *Config) (*Controller, error) { + c := &Controller{ + config: cfg, + } + + if n, err := network.NewNetwork(cfg.Id, cfg.Network, cfg.Db, cfg.Metrics); err == nil { + c.network = n + } else { + return nil, err + } + + if err := c.showOptions(); err != nil { + return nil, err + } + + return c, nil +} + +func (c *Controller) Run() error { + c.startProfiling() + + if err := c.registerComponents(); err != nil { + return fmt.Errorf("error registering component: %s", err) + } + + /** + * ctrl listener/accepter. + */ + c.ctrlListener = channel2.NewClassicListener(c.config.Id, c.config.Ctrl.Listener) + if err := c.ctrlListener.Listen(c.ctrlConnectHandler); err != nil { + panic(err) + } + ctrlAccepter := handler_ctrl.NewCtrlAccepter(c.network, c.xctrls, c.ctrlListener, c.config.Ctrl.Options) + go ctrlAccepter.Run() + /* */ + + /** + * mgmt listener/accepter. + */ + c.mgmtListener = channel2.NewClassicListener(c.config.Id, c.config.Mgmt.Listener) + if err := c.mgmtListener.Listen(c.mgmtConnectHandler); err != nil { + panic(err) + } + mgmtAccepter := handler_mgmt.NewMgmtAccepter(c.mgmtListener, c.config.Mgmt.Options) + go mgmtAccepter.Run() + /* */ + + c.network.Run() + + return nil +} + +func (c *Controller) Shutdown() { + if c.ctrlListener != nil { + if err := c.ctrlListener.Close(); err != nil { + pfxlog.Logger().WithError(err).Error("failed to close ctrl channel listener") + } + } + + if c.mgmtListener != nil { + if err := c.mgmtListener.Close(); err != nil { + pfxlog.Logger().WithError(err).Error("failed to close mgmt channel listener") + } + } + + c.network.Shutdown() +} + +func (c *Controller) showOptions() error { + if ctrl, err := json.MarshalIndent(c.config.Ctrl.Options, "", " "); err == nil { + pfxlog.Logger().Infof("ctrl = %s", string(ctrl)) + } else { + return err + } + if mgmt, err := json.MarshalIndent(c.config.Mgmt.Options, "", " "); err == nil { + pfxlog.Logger().Infof("mgmt = %s", string(mgmt)) + } else { + return err + } + return nil +} + +func (c *Controller) startProfiling() { + if c.config.Profile.Memory.Path != "" { + go profiler.NewMemory(c.config.Profile.Memory.Path, c.config.Profile.Memory.Interval).Run() + } +} + +func (c *Controller) registerComponents() error { + c.ctrlConnectHandler = handler_ctrl.NewConnectHandler(c.network, c.xctrls) + c.mgmtConnectHandler = handler_mgmt.NewConnectHandler(c.network) + + c.config.Mgmt.Options.BindHandlers = []channel2.BindHandler{handler_mgmt.NewBindHandler(c.network, c.xmgmts)} + + if err := c.RegisterXctrl(xctrl_example.NewExample()); err != nil { + return err + } + + return nil +} + +func (c *Controller) RegisterXctrl(x xctrl.Xctrl) error { + if err := c.config.Configure(x); err != nil { + return err + } + if x.Enabled() { + c.xctrls = append(c.xctrls, x) + } + return nil +} + +func (c *Controller) RegisterXmgmt(x xmgmt.Xmgmt) error { + if err := c.config.Configure(x); err != nil { + return err + } + if x.Enabled() { + c.xmgmts = append(c.xmgmts, x) + } + return nil +} + +func (c *Controller) GetNetwork() *network.Network { + return c.network +} diff --git a/fabric/controller/db/db.go b/fabric/controller/db/db.go new file mode 100644 index 000000000..19052dc77 --- /dev/null +++ b/fabric/controller/db/db.go @@ -0,0 +1,70 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package db + +import ( + "errors" + "fmt" + "go.etcd.io/bbolt" +) + +type Db struct { + db *bbolt.DB +} + +func Open(path string) (*Db, error) { + db, err := bbolt.Open(path, 0600, nil) + if err != nil { + return nil, fmt.Errorf("unable to open controller database [%s] (%s)", path, err) + } + if err := db.Update(createRoots); err != nil { + return nil, err + } + return &Db{db: db}, nil +} + +func (db *Db) Close() error { + return db.db.Close() +} + +func (db *Db) Update(fn func(tx *bbolt.Tx) error) error { + return db.db.Update(fn) +} + +func (db *Db) View(fn func(tx *bbolt.Tx) error) error { + return db.db.View(fn) +} + +func (db *Db) RootBucket(tx *bbolt.Tx) (*bbolt.Bucket, error) { + ziti := tx.Bucket([]byte("ziti")) + if ziti == nil { + return nil, errors.New("db missing 'ziti' root") + } + return ziti, nil +} + +func createRoots(tx *bbolt.Tx) error { + if ziti, err := tx.CreateBucketIfNotExists([]byte("ziti")); err == nil { + if _, err := ziti.CreateBucketIfNotExists([]byte("services")); err != nil { + return err + } + if _, err := ziti.CreateBucketIfNotExists([]byte("routers")); err != nil { + return err + } + } + return nil +} \ No newline at end of file diff --git a/fabric/controller/handler_ctrl/accept.go b/fabric/controller/handler_ctrl/accept.go new file mode 100644 index 000000000..9d76323e0 --- /dev/null +++ b/fabric/controller/handler_ctrl/accept.go @@ -0,0 +1,90 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/transport" +) + +type CtrlAccepter struct { + network *network.Network + xctrls []xctrl.Xctrl + listener channel2.UnderlayListener + options *channel2.Options +} + +func NewCtrlAccepter(network *network.Network, + xctrls []xctrl.Xctrl, + listener channel2.UnderlayListener, + options *channel2.Options) *CtrlAccepter { + return &CtrlAccepter{ + network: network, + xctrls: xctrls, + listener: listener, + options: options, + } +} + +func (ctrlAccepter *CtrlAccepter) Run() { + log := pfxlog.Logger() + log.Info("started") + defer log.Warn("exited") + + for { + ch, err := channel2.NewChannel("ctrl", ctrlAccepter.listener, ctrlAccepter.options) + if err == nil { + if r, err := ctrlAccepter.network.KnownRouter(ch.Id().Token); err == nil { + if ch.Underlay().Headers() != nil { + if listenerValue, found := ch.Underlay().Headers()[channel2.HelloListenerHeader]; found { + listenerString := string(listenerValue) + if listener, err := transport.ParseAddress(listenerString); err == nil { + r.AdvertisedListener = listener + } else { + log.Errorf("error parsing listener address (%s)", err) + _ = ch.Close() + continue + } + } else { + log.Warn("missing listener attribute") + } + } else { + log.Warn("no attributes provided") + } + + r.Control = ch + if err := r.Control.Bind(newBindHandler(r, ctrlAccepter.network, ctrlAccepter.xctrls)); err != nil { + log.Errorf("error binding router (%s)", err) + _ = ch.Close() + continue + } + ctrlAccepter.network.ConnectRouter(r) + + log.Infof("accepted new router connection [r/%s]", r.Id) + } + + } else { + log.Errorf("error accepting (%s)", err) + if err.Error() == "closed" { + return + } + } + } +} diff --git a/fabric/controller/handler_ctrl/bind.go b/fabric/controller/handler_ctrl/bind.go new file mode 100644 index 000000000..6ae78583d --- /dev/null +++ b/fabric/controller/handler_ctrl/bind.go @@ -0,0 +1,62 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" +) + +type bindHandler struct { + router *network.Router + network *network.Network + xctrls []xctrl.Xctrl +} + +func newBindHandler(router *network.Router, network *network.Network, xctrls []xctrl.Xctrl) *bindHandler { + return &bindHandler{router: router, network: network, xctrls: xctrls} +} + +func (bindHandler *bindHandler) BindChannel(ch channel2.Channel) error { + ch.SetLogicalName(bindHandler.router.Id) + ch.AddReceiveHandler(newSessionRequestHandler(bindHandler.router, bindHandler.network)) + ch.AddReceiveHandler(newHostRequestHandler(bindHandler.router, bindHandler.network)) + ch.AddReceiveHandler(newLinkHandler(bindHandler.router, bindHandler.network)) + ch.AddReceiveHandler(newFaultHandler(bindHandler.router, bindHandler.network)) + ch.AddReceiveHandler(newMetricsHandler(bindHandler.network)) + ch.AddReceiveHandler(bindHandler.network.GetTraceEventController()) + ch.AddReceiveHandler(newInspectHandler(bindHandler.network)) + ch.AddPeekHandler(trace.NewChannelPeekHandler(bindHandler.network.GetAppId(), ch, bindHandler.network.GetTraceController(), bindHandler.network.GetTraceEventController())) + + xctrlDone := make(chan struct{}) + for _, x := range bindHandler.xctrls { + if err := ch.Bind(x); err != nil { + return err + } + if err := x.Run(ch, bindHandler.network.GetDb(), xctrlDone); err != nil { + return err + } + } + if len(bindHandler.xctrls) > 0 { + ch.AddCloseHandler(newXctrlCloseHandler(xctrlDone)) + } + + ch.AddCloseHandler(newCloseHandler(bindHandler.router, bindHandler.network)) + return nil +} diff --git a/fabric/controller/handler_ctrl/bind_service_request.go b/fabric/controller/handler_ctrl/bind_service_request.go new file mode 100644 index 000000000..24782a3c9 --- /dev/null +++ b/fabric/controller/handler_ctrl/bind_service_request.go @@ -0,0 +1,74 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type hostRequestHandler struct { + r *network.Router + network *network.Network +} + +var successResponse = &ctrl_pb.BindResponse{Success: true} + +func newHostRequestHandler(r *network.Router, network *network.Network) *hostRequestHandler { + return &hostRequestHandler{r: r, network: network} +} + +func (h *hostRequestHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_BindRequestType) +} + +func (h *hostRequestHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + request := &ctrl_pb.BindRequest{} + if err := proto.Unmarshal(msg.Body, request); err != nil { + log.Errorf("unexpected error (%s)", err) + return + } + + response := successResponse + + var err error + if request.BindType == ctrl_pb.BindType_Bind { + err = h.network.BindService(h.r, request.Token, request.ServiceId) + } else if request.BindType == ctrl_pb.BindType_Unbind { + err = h.network.UnbindService(h.r, request.Token, request.ServiceId) + } + + if err != nil { + log.Errorf("unexpected error (%s)", err) + response = &ctrl_pb.BindResponse{Success: false, Message: err.Error()} + } + + if body, err := proto.Marshal(response); err == nil { + responseMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_BindResponseType), body) + responseMsg.ReplyTo(msg) + if err := h.r.Control.Send(responseMsg); err != nil { + log.Errorf("unable to respond (%s)", err) + } + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/controller/handler_ctrl/close.go b/fabric/controller/handler_ctrl/close.go new file mode 100644 index 000000000..b89f2a3fd --- /dev/null +++ b/fabric/controller/handler_ctrl/close.go @@ -0,0 +1,51 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/michaelquigley/pfxlog" +) + +type closeHandler struct { + r *network.Router + network *network.Network +} + +func newCloseHandler(r *network.Router, network *network.Network) *closeHandler { + return &closeHandler{r: r, network: network} +} + +func (h *closeHandler) HandleClose(ch channel2.Channel) { + log := pfxlog.ContextLogger("r/" + h.r.Id) + log.Warn("disconnected") + h.network.DisconnectRouter(h.r) +} + +type xctrlCloseHandler struct { + done chan struct{} +} + +func newXctrlCloseHandler(done chan struct{}) channel2.CloseHandler { + return &xctrlCloseHandler{done: done} +} + +func (h *xctrlCloseHandler) HandleClose(ch channel2.Channel) { + pfxlog.ContextLogger(ch.Label()).Info("closing Xctrl instances") + close(h.done) +} \ No newline at end of file diff --git a/fabric/controller/handler_ctrl/connect.go b/fabric/controller/handler_ctrl/connect.go new file mode 100644 index 000000000..3949aa4db --- /dev/null +++ b/fabric/controller/handler_ctrl/connect.go @@ -0,0 +1,74 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "crypto/sha1" + "crypto/x509" + "errors" + "fmt" + "github.com/michaelquigley/pfxlog" +) + +type ConnectHandler struct { + network *network.Network + xctrls []xctrl.Xctrl +} + +func NewConnectHandler(network *network.Network, xctrls []xctrl.Xctrl) *ConnectHandler { + return &ConnectHandler{network: network, xctrls: xctrls} +} + +func (h *ConnectHandler) HandleConnection(hello *channel2.Hello, certificates []*x509.Certificate) error { + log := pfxlog.ContextLogger(hello.IdToken) + + id := hello.IdToken + + /* + * Control channel connections dump the client-supplied certificate details. We'll + * soon be using these certificates for router enrollment. + */ + fingerprint := "" + if certificates != nil { + log.Debugf("peer has [%d] certificates", len(certificates)) + for i, c := range certificates { + fingerprint = fmt.Sprintf("%x", sha1.Sum(c.Raw)) + log.Debugf("%d): peer certificate fingerprint [%s]", i, fingerprint) + log.Debugf("%d): peer common name [%s]", i, c.Subject.CommonName) + } + } else { + log.Warnf("peer has no certificates") + } + /* */ + + if h.network.ConnectedRouter(id) { + return errors.New("router already connected") + } + + if r, err := h.network.KnownRouter(id); err == nil { + if r.Fingerprint != fingerprint { + return errors.New("unenrolled router") + } + } else { + return errors.New("unenrolled router") + } + + return nil +} diff --git a/fabric/controller/handler_ctrl/fault.go b/fabric/controller/handler_ctrl/fault.go new file mode 100644 index 000000000..0b7ac1637 --- /dev/null +++ b/fabric/controller/handler_ctrl/fault.go @@ -0,0 +1,76 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type faultHandler struct { + r *network.Router + network *network.Network +} + +func newFaultHandler(r *network.Router, network *network.Network) *faultHandler { + return &faultHandler{r: r, network: network} +} + +func (h *faultHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_FaultType) +} + +func (h *faultHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + fault := &ctrl_pb.Fault{} + if err := proto.Unmarshal(msg.Body, fault); err == nil { + switch fault.Subject { + case ctrl_pb.FaultSubject_LinkFault: + linkId := &identity.TokenId{Token: fault.Id} + if err := h.network.LinkConnected(linkId, false); err == nil { + if link, found := h.network.GetLink(linkId); found { + h.network.LinkChanged(link) + } + log.Infof("link fault [l/%s]", linkId.Token) + } + + case ctrl_pb.FaultSubject_IngressFault: + if err := h.network.RemoveSession(&identity.TokenId{Token: fault.Id}, false); err != nil { + log.Errorf("error handling ingress fault (%s)", err) + } else { + log.Debugf("handled ingress fault for (%s)", fault.Id) + } + + case ctrl_pb.FaultSubject_EgressFault: + if err := h.network.RemoveSession(&identity.TokenId{Token: fault.Id}, false); err != nil { + log.Errorf("error handling egress fault (%s)", err) + } else { + log.Debugf("handled egress fault for (%s)", fault.Id) + } + + default: + log.Errorf("unexpected subject (%s)", fault.Subject.String()) + } + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/controller/handler_ctrl/inspect.go b/fabric/controller/handler_ctrl/inspect.go new file mode 100644 index 000000000..4c73a76d1 --- /dev/null +++ b/fabric/controller/handler_ctrl/inspect.go @@ -0,0 +1,77 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type inspectHandler struct { + network *network.Network +} + +func newInspectHandler(network *network.Network) *inspectHandler { + return &inspectHandler{network: network} +} + +func (h *inspectHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_InspectRequestType) +} + +func (h *inspectHandler) HandleReceive(request *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + inspectRequest := &ctrl_pb.InspectRequest{} + if err := proto.Unmarshal(request.Body, inspectRequest); err != nil { + log.Errorf("unexpected error (%s)", err) + h.respondWithError(ch, request, fmt.Errorf("failed to decode request: (%v)", err).Error()) + } + + response := &ctrl_pb.InspectResponse{Success: true} + for _, value := range inspectRequest.RequestedValues { + if value == "capability" { + for _, capability := range h.network.GetCapabilities() { + response.AddValue("capability", capability) + } + } + } + h.respond(ch, request, response) +} + +func (h *inspectHandler) respondWithError(ch channel2.Channel, request *channel2.Message, errs...string) { + response := &ctrl_pb.InspectResponse{Success: false, Errors: errs } + h.respond(ch, request, response) +} + +func (h *inspectHandler) respond(ch channel2.Channel, request *channel2.Message, response *ctrl_pb.InspectResponse) { + log := pfxlog.ContextLogger(ch.Label()) + + if body, err := proto.Marshal(response); err == nil { + responseMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_InspectResponseType), body) + responseMsg.ReplyTo(request) + if err := ch.Send(responseMsg); err != nil { + log.Errorf("unable to respond to inspect request(%s)", err) + } + } else { + log.Errorf("unexpected error marshalling response (%s)", err) + } +} diff --git a/fabric/controller/handler_ctrl/link.go b/fabric/controller/handler_ctrl/link.go new file mode 100644 index 000000000..ccab47005 --- /dev/null +++ b/fabric/controller/handler_ctrl/link.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type linkHandler struct { + r *network.Router + network *network.Network +} + +func newLinkHandler(r *network.Router, network *network.Network) *linkHandler { + return &linkHandler{r: r, network: network} +} + +func (h *linkHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_LinkType) +} + +func (h *linkHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + link := &ctrl_pb.Link{} + if err := proto.Unmarshal(msg.Body, link); err == nil { + if err := h.network.LinkConnected(&identity.TokenId{Token: link.Id}, true); err == nil { + log.Infof("link connected [l/%s]", link.Id) + } else { + log.Errorf("unexpected error (%s)", err) + } + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/controller/handler_ctrl/metrics.go b/fabric/controller/handler_ctrl/metrics.go new file mode 100644 index 000000000..32c941119 --- /dev/null +++ b/fabric/controller/handler_ctrl/metrics.go @@ -0,0 +1,47 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type metricsHandler struct { + metrics.EventController +} + +func newMetricsHandler(network *network.Network) *metricsHandler { + return &metricsHandler{network.GetMetricsEventController()} +} + +func (h *metricsHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_MetricsType) +} + +func (h *metricsHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + metricsMsg := &ctrl_pb.MetricsMessage{} + if err := proto.Unmarshal(msg.Body, metricsMsg); err == nil { + h.AcceptMetrics(metricsMsg) + } else { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error (%s)", err) + } +} \ No newline at end of file diff --git a/fabric/controller/handler_ctrl/session_request.go b/fabric/controller/handler_ctrl/session_request.go new file mode 100644 index 000000000..8fb5b2745 --- /dev/null +++ b/fabric/controller/handler_ctrl/session_request.go @@ -0,0 +1,83 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/ctrl_msg" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "time" +) + +type sessionRequestHandler struct { + r *network.Router + network *network.Network +} + +func newSessionRequestHandler(r *network.Router, network *network.Network) *sessionRequestHandler { + return &sessionRequestHandler{r: r, network: network} +} + +func (h *sessionRequestHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_SessionRequestType) +} + +func (h *sessionRequestHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + request := &ctrl_pb.SessionRequest{} + if err := proto.Unmarshal(msg.Body, request); err == nil { + /* + * This is running in a goroutine because CreateSession does a 'SendAndWait', which cannot be invoked from + * inside a ReceiveHandler (without parallel support). + */ + go func() { + if session, err := h.network.CreateSession(h.r, &identity.TokenId{Token: request.IngressId}, request.ServiceId); err == nil { + responseMsg := ctrl_msg.NewSessionSuccessMsg(session.Id.Token, session.Circuit.IngressId) + responseMsg.ReplyTo(msg) + if startXgressSession, err := h.r.Control.SendAndWaitWithTimeout(responseMsg, time.Second*10); err != nil { + log.Errorf("unable to respond (%s)", err) + h.network.RemoveSession(session.Id, true) + } else { + if startXgressSession.ContentType == int32(ctrl_pb.ContentType_StartXgressType) { + if err = h.network.StartSessionEgress(session.Id); err != nil { + log.WithError(err).Error("failure starting xgress") + h.network.RemoveSession(session.Id, true) + } + } else { + log.Errorf("unexpected reply to dial response: %v", startXgressSession.ContentType) + h.network.RemoveSession(session.Id, true) + } + } + } else { + responseMsg := ctrl_msg.NewSessionFailedMsg(err.Error()) + responseMsg.ReplyTo(msg) + if err := h.r.Control.Send(responseMsg); err != nil { + log.Errorf("unable to respond (%s)", err) + } + } + }() + /* */ + + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/controller/handler_mgmt/accept.go b/fabric/controller/handler_mgmt/accept.go new file mode 100644 index 000000000..bcaee70a8 --- /dev/null +++ b/fabric/controller/handler_mgmt/accept.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" +) + +type MgmtAccepter struct { + listener channel2.UnderlayListener + options *channel2.Options +} + +func NewMgmtAccepter(listener channel2.UnderlayListener, + options *channel2.Options) *MgmtAccepter { + return &MgmtAccepter{ + listener: listener, + options: options, + } +} + +func (mgmtAccepter *MgmtAccepter) Run() { + log := pfxlog.Logger() + log.Info("started") + defer log.Warn("exited") + + for { + ch, err := channel2.NewChannel("mgmt", mgmtAccepter.listener, mgmtAccepter.options) + if err == nil { + log.Debugf("accepted mgmt connection [%s]", ch.Id().Token) + + } else { + log.Errorf("error accepting (%s)", err) + if err.Error() == "closed" { + return + } + } + } +} \ No newline at end of file diff --git a/fabric/controller/handler_mgmt/bind.go b/fabric/controller/handler_mgmt/bind.go new file mode 100644 index 000000000..fed751290 --- /dev/null +++ b/fabric/controller/handler_mgmt/bind.go @@ -0,0 +1,80 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-fabric/fabric/xmgmt" +) + +type BindHandler struct { + network *network.Network + xmgmts []xmgmt.Xmgmt +} + +func NewBindHandler(network *network.Network, xmgmts []xmgmt.Xmgmt) *BindHandler { + return &BindHandler{network: network, xmgmts: xmgmts} +} + +func (bindHandler *BindHandler) BindChannel(ch channel2.Channel) error { + network := bindHandler.network + ch.AddReceiveHandler(newCreateRouterHandler(network)) + ch.AddReceiveHandler(newCreateServiceHandler(network)) + ch.AddReceiveHandler(newGetServiceHandler(network)) + ch.AddReceiveHandler(newInspectHandler(network)) + ch.AddReceiveHandler(newListLinksHandler(network)) + ch.AddReceiveHandler(newListRoutersHandler(network)) + ch.AddReceiveHandler(newListServicesHandler(network)) + ch.AddReceiveHandler(newListSessionsHandler(network)) + ch.AddReceiveHandler(newRemoveRouterHandler(network)) + ch.AddReceiveHandler(newRemoveServiceHandler(network)) + ch.AddReceiveHandler(newRemoveSessionHandler(network)) + ch.AddReceiveHandler(newSetLinkCostHandler(network)) + ch.AddReceiveHandler(newSetLinkDownHandler(network)) + + streamMetricHandler := newStreamMetricsHandler(network) + ch.AddReceiveHandler(streamMetricHandler) + ch.AddCloseHandler(streamMetricHandler) + + streamSessionsHandler := newStreamSessionsHandler(network) + ch.AddReceiveHandler(streamSessionsHandler) + ch.AddCloseHandler(streamSessionsHandler) + + streamTracesHandler := newStreamTracesHandler(network) + ch.AddReceiveHandler(streamTracesHandler) + ch.AddCloseHandler(streamTracesHandler) + + ch.AddReceiveHandler(newTogglePipeTracesHandler(network)) + ch.AddPeekHandler(trace.NewChannelPeekHandler(network.GetAppId(), ch, network.GetTraceController(), network.GetTraceEventController())) + + xmgmtDone := make(chan struct{}) + for _, x := range bindHandler.xmgmts { + if err := ch.Bind(x); err != nil { + return err + } + if err := x.Run(ch, xmgmtDone); err != nil { + return err + } + } + if len(bindHandler.xmgmts) > 0 { + ch.AddCloseHandler(newXmgmtCloseHandler(xmgmtDone)) + } + + return nil +} diff --git a/fabric/controller/handler_mgmt/close.go b/fabric/controller/handler_mgmt/close.go new file mode 100644 index 000000000..8bce02c7f --- /dev/null +++ b/fabric/controller/handler_mgmt/close.go @@ -0,0 +1,35 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/michaelquigley/pfxlog" +) + +type xmgmtCloseHandler struct { + done chan struct{} +} + +func newXmgmtCloseHandler(done chan struct{}) channel2.CloseHandler { + return &xmgmtCloseHandler{done: done} +} + +func (h *xmgmtCloseHandler) HandleClose(ch channel2.Channel) { + pfxlog.Logger().Infof("closing Xmgmt instances for [%s]", ch.Label()) + close(h.done) +} diff --git a/fabric/controller/handler_mgmt/connect.go b/fabric/controller/handler_mgmt/connect.go new file mode 100644 index 000000000..e529ff845 --- /dev/null +++ b/fabric/controller/handler_mgmt/connect.go @@ -0,0 +1,58 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "crypto/x509" + "github.com/michaelquigley/pfxlog" +) + +type ConnectHandler struct { + network *network.Network +} + +func NewConnectHandler(network *network.Network) *ConnectHandler { + return &ConnectHandler{ + network: network, + } +} + +func (h *ConnectHandler) HandleConnection(hello *channel2.Hello, certificates []*x509.Certificate) error { + return nil +} + +func sendSuccess(request *channel2.Message, ch channel2.Channel, message string) { + sendResult(request, ch, message, true) +} + +func sendFailure(request *channel2.Message, ch channel2.Channel, message string) { + sendResult(request, ch, message, false) +} + +func sendResult(request *channel2.Message, ch channel2.Channel, message string, success bool) { + log := pfxlog.ContextLogger(ch.Label()) + if !success { + log.Errorf("mgmt error (%s)", message) + } + + response := channel2.NewResult(success, message) + response.ReplyTo(request) + _ = ch.Send(response) + log.Debug("success") +} diff --git a/fabric/controller/handler_mgmt/create_router.go b/fabric/controller/handler_mgmt/create_router.go new file mode 100644 index 000000000..e799199c2 --- /dev/null +++ b/fabric/controller/handler_mgmt/create_router.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type createRouterHandler struct { + network *network.Network +} + +func newCreateRouterHandler(network *network.Network) *createRouterHandler { + return &createRouterHandler{network: network} +} + +func (h *createRouterHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_CreateRouterRequestType) +} + +func (h *createRouterHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + create := &mgmt_pb.CreateRouterRequest{} + if err := proto.Unmarshal(msg.Body, create); err == nil { + r := network.NewRouter(create.Router.Id, create.Router.Fingerprint) + if err := h.network.CreateRouter(r); err == nil { + log.Infof("created router [r/%s] with fingerprint [%s]", r.Id, r.Fingerprint) + sendSuccess(msg, ch, "") + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/create_service.go b/fabric/controller/handler_mgmt/create_service.go new file mode 100644 index 000000000..f96ccf26e --- /dev/null +++ b/fabric/controller/handler_mgmt/create_service.go @@ -0,0 +1,59 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" +) + +type createServiceHandler struct { + network *network.Network +} + +func newCreateServiceHandler(network *network.Network) *createServiceHandler { + return &createServiceHandler{network: network} +} + +func (h *createServiceHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_CreateServiceRequestType) +} + +func (h *createServiceHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + cs := &mgmt_pb.CreateServiceRequest{} + err := proto.Unmarshal(msg.Body, cs) + if err == nil { + binding := "transport" + if cs.Service.Binding != "" { + binding = cs.Service.Binding + } + if err = h.network.CreateService(&network.Service{ + Id: cs.Service.Id, + Binding: binding, + EndpointAddress: cs.Service.EndpointAddress, + Egress: cs.Service.Egress, + }); err == nil { + sendSuccess(msg, ch, "") + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/get_service.go b/fabric/controller/handler_mgmt/get_service.go new file mode 100644 index 000000000..1037fc23b --- /dev/null +++ b/fabric/controller/handler_mgmt/get_service.go @@ -0,0 +1,68 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type getServiceHandler struct { + network *network.Network +} + +func newGetServiceHandler(network *network.Network) *getServiceHandler { + return &getServiceHandler{network: network} +} + +func (h *getServiceHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_GetServiceRequestType) +} + +func (h *getServiceHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + rs := &mgmt_pb.GetServiceRequest{} + err := proto.Unmarshal(msg.Body, rs) + if err == nil { + response := &mgmt_pb.GetServiceResponse{} + if svc, found := h.network.GetService(rs.ServiceId); found { + response.Service = &mgmt_pb.Service{ + Id: svc.Id, + Binding: svc.Binding, + EndpointAddress: svc.EndpointAddress, + Egress: svc.Egress, + } + + body, err := proto.Marshal(response) + if err == nil { + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_GetServiceResponseType), body) + responseMsg.ReplyTo(msg) + ch.Send(responseMsg) + + } else { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error (%s)", err) + } + + } else { + sendFailure(msg, ch, "no such service") + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/inspect.go b/fabric/controller/handler_mgmt/inspect.go new file mode 100644 index 000000000..3416e1c84 --- /dev/null +++ b/fabric/controller/handler_mgmt/inspect.go @@ -0,0 +1,196 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/util/debugz" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "regexp" + "strings" + "sync" + "time" +) + +type inspectHandler struct { + network *network.Network +} + +func newInspectHandler(network *network.Network) *inspectHandler { + return &inspectHandler{network: network} +} + +func (*inspectHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_InspectRequestType) +} + +func (handler *inspectHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + context := &inspectRequestContext{ + handler: handler, + msg: msg, + ch: ch, + request: &mgmt_pb.InspectRequest{}, + response: &mgmt_pb.InspectResponse{Success: true}, + } + + var err error + if err = proto.Unmarshal(msg.Body, context.request); err != nil { + context.appendError(handler.network.GetAppId().Token, err.Error()) + } + + context.regex, err = regexp.Compile(context.request.AppRegex) + if err != nil { + context.appendError(handler.network.GetAppId().Token, err.Error()) + } + + if !context.response.Success { + context.sendResponse() + return + } + + context.processLocal() + context.processRemote() + context.sendResponse() +} + +type inspectRequestContext struct { + handler *inspectHandler + msg *channel2.Message + ch channel2.Channel + request *mgmt_pb.InspectRequest + response *mgmt_pb.InspectResponse + regex *regexp.Regexp +} + +func (context *inspectRequestContext) processLocal() { + if context.regex.MatchString(context.handler.network.GetAppId().Token) { + for _, requested := range context.request.RequestedValues { + if strings.ToLower(requested) == "stackdump" { + context.appendValue(context.handler.network.GetAppId().Token, requested, debugz.GenerateStack()) + } + } + } +} + +func (context *inspectRequestContext) processRemote() { + routerRequest := &ctrl_pb.InspectRequest{RequestedValues: context.request.RequestedValues} + body, err := proto.Marshal(routerRequest) + if err != nil { + context.appendError(context.handler.network.GetAppId().Token, err.Error()) + return + } + + remoteResultChan := make(chan *remoteInspectResult) + waitGroup := &sync.WaitGroup{} + + for _, router := range context.handler.network.AllConnectedRouters() { + if context.regex.MatchString(router.Id) { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_InspectRequestType), body) + respCh, err := router.Control.SendAndWait(msg) + if err != nil { + context.appendError(router.Id, err.Error()) + } else { + waitGroup.Add(1) + go handleInspectResponse(router.Id, respCh, remoteResultChan, waitGroup) + } + } + } + + // Close chan once all results have been queued + go func() { + waitGroup.Wait() + close(remoteResultChan) + }() + + for remoteResult := range remoteResultChan { + for _, err := range remoteResult.result.Errors { + context.appendError(remoteResult.appId, err) + } + for _, val := range remoteResult.result.Values { + context.appendValue(remoteResult.appId, val.Name, val.Value) + } + } +} + +func handleInspectResponse(appId string, respCh <-chan *channel2.Message, msgsCh chan<- *remoteInspectResult, waitGroup *sync.WaitGroup) { + defer waitGroup.Done() + + timeout := time.After(time.Second * 5) + + select { + case response, ok := <-respCh: + if !ok { + routerInspectFailed(appId, msgsCh, "no response from router") + } else if response.ContentType == int32(ctrl_pb.ContentType_InspectResponseType) { + result := &ctrl_pb.InspectResponse{} + if err := proto.Unmarshal(response.Body, result); err != nil { + routerInspectFailed(appId, msgsCh, fmt.Sprintf("Failed to decode response from router: %v", err)) + } else { + msgsCh <- &remoteInspectResult{appId: appId, result: result} + } + } else { + msg := fmt.Sprintf("Unexpected response type from router %v: %v\n", appId, response.ContentType) + routerInspectFailed(appId, msgsCh, msg) + } + case <-timeout: + routerInspectFailed(appId, msgsCh, "timed out waiting for response from router") + } +} + +func routerInspectFailed(appId string, msgsCh chan<- *remoteInspectResult, msg string) { + msgsCh <- &remoteInspectResult{ + appId: appId, + result: &ctrl_pb.InspectResponse{Errors: []string{msg}}, + } +} + +func (context *inspectRequestContext) sendResponse() { + body, err := proto.Marshal(context.response) + if err != nil { + pfxlog.Logger().Errorf("unexpected error serializing InspectResponse (%s)", err) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_InspectResponseType), body) + responseMsg.ReplyTo(context.msg) + if err := context.ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending InspectResponse (%s)", err) + } +} + +func (context *inspectRequestContext) appendValue(appId string, name string, value string) { + context.response.Values = append(context.response.Values, &mgmt_pb.InspectResponse_InspectValue{ + AppId: appId, + Name: name, + Value: value, + }) +} + +func (context *inspectRequestContext) appendError(appId string, err string) { + context.response.Success = false + context.response.Errors = append(context.response.Errors, fmt.Sprintf("%v: %v", appId, err)) +} + +type remoteInspectResult struct { + appId string + result *ctrl_pb.InspectResponse +} diff --git a/fabric/controller/handler_mgmt/list_links.go b/fabric/controller/handler_mgmt/list_links.go new file mode 100644 index 000000000..243518415 --- /dev/null +++ b/fabric/controller/handler_mgmt/list_links.go @@ -0,0 +1,75 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type listLinksHandler struct { + network *network.Network +} + +func newListLinksHandler(network *network.Network) *listLinksHandler { + return &listLinksHandler{network: network} +} + +func (h *listLinksHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_ListLinksRequestType) +} + +func (h *listLinksHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + list := &mgmt_pb.ListLinksRequest{} + if err := proto.Unmarshal(msg.Body, list); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + links := h.network.GetAllLinks() + response := &mgmt_pb.ListLinksResponse{ + Links: make([]*mgmt_pb.Link, 0), + } + for _, l := range links { + responseLink := &mgmt_pb.Link{ + Id: l.Id.Token, + Src: l.Src.Id, + Dst: l.Dst.Id, + State: l.CurrentState().Mode.String(), + Down: l.Down, + Cost: int32(l.Cost), + SrcLatency: l.SrcLatency, + DstLatency: l.DstLatency, + } + response.Links = append(response.Links, responseLink) + } + + body, err := proto.Marshal(response) + if err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListLinksResponseType), body) + responseMsg.ReplyTo(msg) + if err := ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending response (%s)", err) + } +} diff --git a/fabric/controller/handler_mgmt/list_routers.go b/fabric/controller/handler_mgmt/list_routers.go new file mode 100644 index 000000000..53c5bf17e --- /dev/null +++ b/fabric/controller/handler_mgmt/list_routers.go @@ -0,0 +1,79 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type listRoutersHandler struct { + network *network.Network +} + +func newListRoutersHandler(network *network.Network) *listRoutersHandler { + return &listRoutersHandler{network: network} +} + +func (h *listRoutersHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_ListRoutersRequestType) +} + +func (h *listRoutersHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + list := &mgmt_pb.ListRoutersRequest{} + if err := proto.Unmarshal(msg.Body, list); err == nil { + response := &mgmt_pb.ListRoutersResponse{Routers: make([]*mgmt_pb.Router, 0)} + if routers, err := h.network.AllRouters(); err == nil { + log.Infof("got [%d] routers", len(routers)) + for _, r := range routers { + connected := false + if connR, found := h.network.GetConnectedRouter(r.Id); found { + connected = true + r.AdvertisedListener = connR.AdvertisedListener + } + responseR := &mgmt_pb.Router{ + Id: r.Id, + Fingerprint: r.Fingerprint, + Connected: connected, + } + if r.AdvertisedListener != nil { + responseR.ListenerAddress = r.AdvertisedListener.String() + } + response.Routers = append(response.Routers, responseR) + } + + if body, err := proto.Marshal(response); err == nil { + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListRoutersResponseType), body) + responseMsg.ReplyTo(msg) + if err := ch.Send(responseMsg); err != nil { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error sending response (%s)", err) + } + + } else { + sendFailure(msg, ch, err.Error()) + } + + } else { + sendFailure(msg, ch, err.Error()) + } + } +} diff --git a/fabric/controller/handler_mgmt/list_services.go b/fabric/controller/handler_mgmt/list_services.go new file mode 100644 index 000000000..e61ee6c28 --- /dev/null +++ b/fabric/controller/handler_mgmt/list_services.go @@ -0,0 +1,72 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type listServicesHandler struct { + network *network.Network +} + +func newListServicesHandler(network *network.Network) *listServicesHandler { + return &listServicesHandler{network: network} +} + +func (h *listServicesHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_ListServicesRequestType) +} + +func (h *listServicesHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + ls := &mgmt_pb.ListServicesRequest{} + err := proto.Unmarshal(msg.Body, ls) + if err == nil { + response := &mgmt_pb.ListServicesResponse{Services: make([]*mgmt_pb.Service, 0)} + svcs, err := h.network.AllServices() + if err == nil { + for _, s := range svcs { + response.Services = append(response.Services, &mgmt_pb.Service{ + Id: s.Id, + Binding: s.Binding, + EndpointAddress: s.EndpointAddress, + Egress: s.Egress, + }) + } + + body, err := proto.Marshal(response) + if err == nil { + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListServicesResponseType), body) + responseMsg.ReplyTo(msg) + if err := ch.Send(responseMsg); err != nil { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error sending response (%s)", err) + } + + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/list_sessions.go b/fabric/controller/handler_mgmt/list_sessions.go new file mode 100644 index 000000000..32a03d6c9 --- /dev/null +++ b/fabric/controller/handler_mgmt/list_sessions.go @@ -0,0 +1,81 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type listSessionsHandler struct { + network *network.Network +} + +func newListSessionsHandler(network *network.Network) *listSessionsHandler { + return &listSessionsHandler{network: network} +} + +func (h *listSessionsHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_ListSessionsRequestType) +} + +func (h *listSessionsHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + list := &mgmt_pb.ListSessionsRequest{} + if err := proto.Unmarshal(msg.Body, list); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + sessions := h.network.GetAllSessions() + response := &mgmt_pb.ListSessionsResponse{ + Sessions: make([]*mgmt_pb.Session, 0), + } + for _, s := range sessions { + responseSession := &mgmt_pb.Session{ + Id: s.Id.Token, + ClientId: s.ClientId.Token, + ServiceId: s.Service.Id, + Circuit: NewCircuit(s.Circuit), + } + response.Sessions = append(response.Sessions, responseSession) + } + body, err := proto.Marshal(response) + if err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_ListSessionsResponseType), body) + responseMsg.ReplyTo(msg) + if err := ch.Send(responseMsg); err != nil { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error sending response (%s)", err) + } +} + +func NewCircuit(circuit *network.Circuit) *mgmt_pb.Circuit { + mgmtCircuit := &mgmt_pb.Circuit{} + for _, r := range circuit.Path { + mgmtCircuit.Path = append(mgmtCircuit.Path, r.Id) + } + for _, l := range circuit.Links { + mgmtCircuit.Links = append(mgmtCircuit.Links, l.Id.Token) + } + return mgmtCircuit +} \ No newline at end of file diff --git a/fabric/controller/handler_mgmt/remove_router.go b/fabric/controller/handler_mgmt/remove_router.go new file mode 100644 index 000000000..c3c3bcfa1 --- /dev/null +++ b/fabric/controller/handler_mgmt/remove_router.go @@ -0,0 +1,58 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type removeRouterHandler struct { + network *network.Network +} + +func newRemoveRouterHandler(network *network.Network) *removeRouterHandler { + return &removeRouterHandler{network: network} +} + +func (h *removeRouterHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_RemoveRouterRequestType) +} + +func (h *removeRouterHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + remove := &mgmt_pb.RemoveRouterRequest{} + if err := proto.Unmarshal(msg.Body, remove); err == nil { + router, err := h.network.GetRouter(remove.RouterId) + if err == nil { + if err := h.network.RemoveRouter(router); err == nil { + log.Infof("removed router [r/%s]", remove.RouterId) + sendSuccess(msg, ch, "") + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/remove_service.go b/fabric/controller/handler_mgmt/remove_service.go new file mode 100644 index 000000000..1d08c65b0 --- /dev/null +++ b/fabric/controller/handler_mgmt/remove_service.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" +) + +type removeServiceHandler struct { + network *network.Network +} + +func newRemoveServiceHandler(network *network.Network) *removeServiceHandler { + return &removeServiceHandler{network: network} +} + +func (h *removeServiceHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_RemoveServiceRequestType) +} + +func (h *removeServiceHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + rs := &mgmt_pb.RemoveServiceRequest{} + err := proto.Unmarshal(msg.Body, rs) + if err == nil { + if svc, found := h.network.GetService(rs.ServiceId); found { + if err := h.network.RemoveService(svc.Id); err != nil { + sendFailure(msg, ch, err.Error()) + } else { + sendSuccess(msg, ch, "") + } + } else { + sendFailure(msg, ch, "no such service") + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/remove_session.go b/fabric/controller/handler_mgmt/remove_session.go new file mode 100644 index 000000000..ab0352b3a --- /dev/null +++ b/fabric/controller/handler_mgmt/remove_session.go @@ -0,0 +1,53 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type removeSessionHandler struct { + network *network.Network +} + +func newRemoveSessionHandler(network *network.Network) *removeSessionHandler { + return &removeSessionHandler{network: network} +} + +func (handler *removeSessionHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_RemoveSessionRequestType) +} + +func (handler *removeSessionHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &mgmt_pb.RemoveSessionRequest{} + if err := proto.Unmarshal(msg.Body, request); err == nil { + sessionId := &identity.TokenId{Token: request.SessionId} + if err := handler.network.RemoveSession(sessionId, request.Now); err == nil { + sendSuccess(msg, ch, "") + } else { + pfxlog.Logger().Errorf("unexpected error removing session s/[%s] (%s)", sessionId.Token, err) + sendFailure(msg, ch, err.Error()) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/set_link_cost.go b/fabric/controller/handler_mgmt/set_link_cost.go new file mode 100644 index 000000000..efd73908b --- /dev/null +++ b/fabric/controller/handler_mgmt/set_link_cost.go @@ -0,0 +1,57 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type setLinkCostHandler struct { + network *network.Network +} + +func newSetLinkCostHandler(network *network.Network) *setLinkCostHandler { + return &setLinkCostHandler{network: network} +} + +func (h *setLinkCostHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_SetLinkCostRequestType) +} + +func (h *setLinkCostHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + set := &mgmt_pb.SetLinkCostRequest{} + if err := proto.Unmarshal(msg.Body, set); err == nil { + if l, found := h.network.GetLink(&identity.TokenId{Token: set.LinkId}); found { + l.Cost = int(set.Cost) + h.network.LinkChanged(l) + log.Infof("set cost of link [l/%s] to [%d]", set.LinkId, set.Cost) + sendSuccess(msg, ch, "") + } else { + sendFailure(msg, ch, fmt.Sprintf("unknown link [l/%s]", set.LinkId)) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/set_link_down.go b/fabric/controller/handler_mgmt/set_link_down.go new file mode 100644 index 000000000..7b747e183 --- /dev/null +++ b/fabric/controller/handler_mgmt/set_link_down.go @@ -0,0 +1,57 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type setLinkDownHandler struct { + network *network.Network +} + +func newSetLinkDownHandler(network *network.Network) *setLinkDownHandler { + return &setLinkDownHandler{network: network} +} + +func (h *setLinkDownHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_SetLinkDownRequestType) +} + +func (h *setLinkDownHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + set := &mgmt_pb.SetLinkDownRequest{} + if err := proto.Unmarshal(msg.Body, set); err == nil { + if l, found := h.network.GetLink(&identity.TokenId{Token: set.LinkId}); found { + l.Down = set.Down + h.network.LinkChanged(l) + log.Infof("set down state of link [l/%s] to [%t]", set.LinkId, set.Down) + sendSuccess(msg, ch, "") + } else { + sendFailure(msg, ch, fmt.Sprintf("unknown link [l/%s]", set.LinkId)) + } + } else { + sendFailure(msg, ch, err.Error()) + } +} diff --git a/fabric/controller/handler_mgmt/stream_metrics.go b/fabric/controller/handler_mgmt/stream_metrics.go new file mode 100644 index 000000000..130fbaf22 --- /dev/null +++ b/fabric/controller/handler_mgmt/stream_metrics.go @@ -0,0 +1,235 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes/timestamp" + "github.com/michaelquigley/pfxlog" + "regexp" +) + +type streamMetricsHandler struct { + network *network.Network + streamHandlers []metrics.Handler +} + +func newStreamMetricsHandler(network *network.Network) *streamMetricsHandler { + return &streamMetricsHandler{network: network} +} + +func (*streamMetricsHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_StreamMetricsRequestType) +} + +func (handler *streamMetricsHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &mgmt_pb.StreamMetricsRequest{} + if err := proto.Unmarshal(msg.Body, request); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + filters, err := parseFilters(request) + if err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + metricsStreamHandler := &MetricsStreamHandler{ + ch: ch, + filters: filters, + eventController: handler.network.GetMetricsEventController(), + } + + handler.streamHandlers = append(handler.streamHandlers, metricsStreamHandler) + handler.network.GetMetricsEventController().AddHandler(metricsStreamHandler) +} + +func (handler *streamMetricsHandler) HandleClose(ch channel2.Channel) { + for _, streamHandler := range handler.streamHandlers { + handler.network.GetMetricsEventController().RemoveHandler(streamHandler) + } +} + +func parseFilters(msg *mgmt_pb.StreamMetricsRequest) ([]*metricsFilter, error) { + var filters []*metricsFilter + for _, filterDef := range msg.Matchers { + filter := &metricsFilter{} + + if filterDef.NameRegex != "" { + regex, err := regexp.Compile(filterDef.NameRegex) + if err != nil { + return nil, err + } + filter.metricFilter = regex + } + + if filterDef.NameRegex != "" { + regex, err := regexp.Compile(filterDef.SourceIDRegex) + if err != nil { + return nil, err + } + filter.sourceFilter = regex + } + + filters = append(filters, filter) + } + return filters, nil +} + +type metricsFilter struct { + sourceFilter *regexp.Regexp + metricFilter *regexp.Regexp +} + +type MetricsStreamHandler struct { + ch channel2.Channel + filters []*metricsFilter + eventController metrics.EventController +} + +func (handler *MetricsStreamHandler) AcceptMetrics(msg *ctrl_pb.MetricsMessage) { + if handler.filters == nil { + handler.filter(nil, msg) + return + } + + var filters []*metricsFilter + for _, filter := range handler.filters { + if filter.sourceFilter == nil || filter.sourceFilter.Match([]byte(msg.SourceId)) { + filters = append(filters, filter) + } + } + if len(filters) > 0 { + handler.filter(filters, msg) + } +} + +func (handler *MetricsStreamHandler) filter(filters []*metricsFilter, msg *ctrl_pb.MetricsMessage) { + event := &mgmt_pb.StreamMetricsEvent{ + SourceId: msg.SourceId, + Timestamp: msg.Timestamp, + Tags: msg.Tags, + } + + for name, value := range msg.IntValues { + filterIntMetric(name, value, event, filters) + } + + for name, value := range msg.FloatValues { + filterFloatMetric(name, value, event, filters) + } + + for name, value := range msg.Meters { + filterIntMetric(name+".count", value.Count, event, filters) + filterFloatMetric(name+".mean_rate", value.MeanRate, event, filters) + filterFloatMetric(name+".m1_rate", value.M1Rate, event, filters) + filterFloatMetric(name+".m5_rate", value.M5Rate, event, filters) + filterFloatMetric(name+".m15_rate", value.M15Rate, event, filters) + } + + for name, value := range msg.Histograms { + filterIntMetric(name+".count", value.Count, event, filters) + filterIntMetric(name+".min", value.Min, event, filters) + filterIntMetric(name+".max", value.Max, event, filters) + filterFloatMetric(name+".mean", value.Mean, event, filters) + filterFloatMetric(name+".std_dev", value.StdDev, event, filters) + filterFloatMetric(name+".variance", value.Variance, event, filters) + filterFloatMetric(name+".p50", value.P50, event, filters) + filterFloatMetric(name+".p75", value.P75, event, filters) + filterFloatMetric(name+".p95", value.P95, event, filters) + filterFloatMetric(name+".p99", value.P99, event, filters) + filterFloatMetric(name+".p999", value.P999, event, filters) + filterFloatMetric(name+".p9999", value.P9999, event, filters) + } + + for name, interval := range msg.IntervalCounters { + if nameMatches(name, filters) { + for _, bucket := range interval.Buckets { + intervalMetric := &mgmt_pb.StreamMetricsEvent_IntervalMetric{ + Name: name, + } + intervalMetric.Values = bucket.Values + intervalMetric.IntervalStartUTC = ×tamp.Timestamp{Seconds: bucket.IntervalStartUTC} + intervalEndSeconds := bucket.IntervalStartUTC + int64(interval.IntervalLength) + intervalMetric.IntervalEndUTC = ×tamp.Timestamp{Seconds: intervalEndSeconds} + + event.IntervalMetrics = append(event.IntervalMetrics, intervalMetric) + } + } + } + + if len(event.IntMetrics) > 0 || len(event.FloatMetrics) > 0 || len(event.IntervalMetrics) > 0 { + handler.send(event) + } +} + +func filterIntMetric(name string, value int64, event *mgmt_pb.StreamMetricsEvent, filters []*metricsFilter) { + if nameMatches(name, filters) { + if event.IntMetrics == nil { + event.IntMetrics = make(map[string]int64) + } + event.IntMetrics[name] = value + } +} + +func filterFloatMetric(name string, value float64, event *mgmt_pb.StreamMetricsEvent, filters []*metricsFilter) { + if nameMatches(name, filters) { + if event.FloatMetrics == nil { + event.FloatMetrics = make(map[string]float64) + } + event.FloatMetrics[name] = value + } +} + +func nameMatches(name string, filters []*metricsFilter) bool { + if len(filters) == 0 { + return true + } + for _, filter := range filters { + if filter.metricFilter == nil || filter.metricFilter.Match([]byte(name)) { + return true + } + } + return false +} + +func (handler *MetricsStreamHandler) send(msg *mgmt_pb.StreamMetricsEvent) { + body, err := proto.Marshal(msg) + if err != nil { + pfxlog.Logger().Errorf("unexpected error serializing StreamMetricsEvent (%s)", err) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_StreamMetricsEventType), body) + if err := handler.ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending StreamMetricsEvent (%s)", err) + handler.close() + } +} + +func (handler *MetricsStreamHandler) close() { + if err := handler.ch.Close(); err != nil { + pfxlog.Logger().WithError(err).Errorf("failure while closing handler") + } + handler.eventController.RemoveHandler(handler) +} diff --git a/fabric/controller/handler_mgmt/stream_sessions.go b/fabric/controller/handler_mgmt/stream_sessions.go new file mode 100644 index 000000000..15a53815e --- /dev/null +++ b/fabric/controller/handler_mgmt/stream_sessions.go @@ -0,0 +1,115 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type streamSessionsHandler struct { + network *network.Network + streamHandlers []network.SessionLifeCycleListener +} + +func newStreamSessionsHandler(network *network.Network) *streamSessionsHandler { + return &streamSessionsHandler{network: network} +} + +func (*streamSessionsHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_StreamSessionsRequestType) +} + +func (handler *streamSessionsHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &mgmt_pb.StreamSessionsRequest{} + if err := proto.Unmarshal(msg.Body, request); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + sessionEventRouter := handler.network.GetSessionLifeCycleController() + sessionsStreamHandler := &SessionsStreamHandler{ + ch: ch, + router: sessionEventRouter, + } + handler.streamHandlers = append(handler.streamHandlers, sessionsStreamHandler) + sessionEventRouter.AddListener(sessionsStreamHandler) +} + +func (handler *streamSessionsHandler) HandleClose(ch channel2.Channel) { + for _, listener := range handler.streamHandlers { + handler.network.GetSessionLifeCycleController().RemoveListener(listener) + } +} + +type SessionsStreamHandler struct { + ch channel2.Channel + router network.SessionLifeCycleController +} + +func (handler *SessionsStreamHandler) SessionCreated(sessionId *identity.TokenId, clientId *identity.TokenId, serviceId string, circuit *network.Circuit) { + event := &mgmt_pb.StreamSessionsEvent{ + EventType: mgmt_pb.StreamSessionEventType_SessionCreated, + SessionId: sessionId.Token, + ClientId: clientId.Token, + ServiceId: serviceId, + Circuit: NewCircuit(circuit), + } + handler.sendEvent(event) +} + +func (handler *SessionsStreamHandler) SessionDeleted(sessionId *identity.TokenId) { + event := &mgmt_pb.StreamSessionsEvent{ + EventType: mgmt_pb.StreamSessionEventType_SessionDeleted, + SessionId: sessionId.Token, + } + handler.sendEvent(event) +} + +func (handler *SessionsStreamHandler) CircuitUpdated(sessionId *identity.TokenId, circuit *network.Circuit) { + event := &mgmt_pb.StreamSessionsEvent{ + EventType: mgmt_pb.StreamSessionEventType_CircuitUpdated, + SessionId: sessionId.Token, + Circuit: NewCircuit(circuit), + } + handler.sendEvent(event) +} + +func (handler *SessionsStreamHandler) sendEvent(event *mgmt_pb.StreamSessionsEvent) { + body, err := proto.Marshal(event) + if err != nil { + pfxlog.Logger().Errorf("unexpected error serializing StreamSessionsEvent (%s)", err) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_StreamSessionsEventType), body) + if err := handler.ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending StreamMetricsEvent (%s)", err) + handler.close() + } +} + +func (handler *SessionsStreamHandler) close() { + if err := handler.ch.Close(); err != nil { + pfxlog.Logger().WithError(err).Error("unexpected error closing mgmt channel") + } + handler.router.RemoveListener(handler) +} diff --git a/fabric/controller/handler_mgmt/stream_toggle_pipe_traces.go b/fabric/controller/handler_mgmt/stream_toggle_pipe_traces.go new file mode 100644 index 000000000..c6c931096 --- /dev/null +++ b/fabric/controller/handler_mgmt/stream_toggle_pipe_traces.go @@ -0,0 +1,171 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-fabric/fabric/trace" + trace_pb "github.com/netfoundry/ziti-foundation/trace/pb" + "fmt" + "github.com/golang/protobuf/proto" + "sync" + "time" +) + +type traceTogglePipeHandler struct { + network *network.Network +} + +func newTogglePipeTracesHandler(network *network.Network) *traceTogglePipeHandler { + return &traceTogglePipeHandler{network: network} +} + +func (*traceTogglePipeHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_TogglePipeTracesRequestType) +} + +func (handler *traceTogglePipeHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &trace_pb.TogglePipeTracesRequest{} + + if err := proto.Unmarshal(msg.Body, request); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + matchers, result := trace.NewPipeToggleMatchers(request) + + if !result.Success { + handler.complete(msg, ch, result) + return + } + + resultChan := make(chan trace.ToggleApplyResult) + + verbosity := trace.GetVerbosity(request.Verbosity) + + if checkMatch(handler.network.GetAppId().Token, matchers, verbosity, result) { + if request.Enable { + handler.network.GetTraceController().EnableTracing(trace.SourceTypePipe, matchers.PipeMatcher, resultChan) + } else { + handler.network.GetTraceController().DisableTracing(trace.SourceTypePipe, matchers.PipeMatcher, resultChan) + } + getApplyResults(resultChan, verbosity, result) + } + + if !result.Success { + handler.complete(msg, ch, result) + return + } + + remoteResultChan := make(chan *remoteToggleResult) + waitGroup := &sync.WaitGroup{} + + for _, router := range handler.network.AllConnectedRouters() { + if checkMatch(router.Id, matchers, verbosity, result) { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_TogglePipeTracesRequestType), msg.Body) + respCh, err := router.Control.SendAndWait(msg) + if err != nil { + result.Success = false + result.Append(fmt.Sprintf("Trace enable of Router %v failed with: %v", router.Id, err)) + } else { + waitGroup.Add(1) + go handleResponse(router.Id, respCh, remoteResultChan, waitGroup) + } + } + } + + // Close chan once all results have been queued + go func() { + waitGroup.Wait() + close(remoteResultChan) + }() + + for remoteToggleResult := range remoteResultChan { + if !remoteToggleResult.success { + result.Success = false + } + result.Message.WriteString(remoteToggleResult.message) + } + + handler.complete(msg, ch, result) +} + +func (handler *traceTogglePipeHandler) complete(msg *channel2.Message, ch channel2.Channel, result *trace.ToggleResult) { + if result.Success { + sendSuccess(msg, ch, result.Message.String()) + } else { + sendFailure(msg, ch, result.Message.String()) + } +} + +func checkMatch(appId string, matchers *trace.PipeToggleMatchers, verbosity trace.ToggleVerbosity, result *trace.ToggleResult) bool { + appMatches := matchers.AppMatcher.Matches(appId) + applyResult := &trace.ToggleApplyResultImpl{ + Matched: appMatches, + Message: fmt.Sprintf("App %v matched? %v", appId, appMatches), + } + applyResult.Append(result, verbosity) + return appMatches +} + +func getApplyResults(resultChan chan trace.ToggleApplyResult, verbosity trace.ToggleVerbosity, result *trace.ToggleResult) { + timout := time.After(time.Second * 5) + for { + select { + case applyResult, chanOpen := <-resultChan: + if !chanOpen { + return + } + applyResult.Append(result, verbosity) + case <-timout: + result.Success = false + result.Append("Timed out waiting for toggle to be applied to controller") + return + } + } +} + +func handleResponse(targetId string, respCh <-chan *channel2.Message, msgsCh chan<- *remoteToggleResult, waitGroup *sync.WaitGroup) { + defer waitGroup.Done() + + timeout := time.After(time.Second * 5) + + select { + case response, ok := <-respCh: + if !ok { + msg := fmt.Sprintf("No response from router %v\n", targetId) + msgsCh <- &remoteToggleResult{false, msg} + } else if response.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(response) + msgsCh <- &remoteToggleResult{result.Success, result.Message} + } else { + msg := fmt.Sprintf("Unexpected response type from router %v: %v\n", targetId, response.ContentType) + msgsCh <- &remoteToggleResult{false, msg} + } + case <-timeout: + msg := fmt.Sprintf("Timed out waiting for response from router %v\n", targetId) + msgsCh <- &remoteToggleResult{false, msg} + } +} + +type remoteToggleResult struct { + success bool + message string +} diff --git a/fabric/controller/handler_mgmt/stream_traces.go b/fabric/controller/handler_mgmt/stream_traces.go new file mode 100644 index 000000000..dcf0f00d4 --- /dev/null +++ b/fabric/controller/handler_mgmt/stream_traces.go @@ -0,0 +1,102 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_mgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/controller/network" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-foundation/trace/pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type streamTracesHandler struct { + network *network.Network + streamHandlers []trace.EventHandler +} + +func newStreamTracesHandler(network *network.Network) *streamTracesHandler { + return &streamTracesHandler{network: network} +} + +func (*streamTracesHandler) ContentType() int32 { + return int32(mgmt_pb.ContentType_StreamTracesRequestType) +} + +func (handler *streamTracesHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &mgmt_pb.StreamTracesRequest{} + if err := proto.Unmarshal(msg.Body, request); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + eventRouter := handler.network.GetTraceEventController() + + filter := createFilter(request) + eventHandler := &traceEventsHandler{ch, eventRouter, filter} + + handler.streamHandlers = append(handler.streamHandlers, eventHandler) + eventRouter.AddHandler(eventHandler) +} + +func (handler *streamTracesHandler) HandleClose(ch channel2.Channel) { + for _, streamHandler := range handler.streamHandlers { + handler.network.GetTraceEventController().RemoveHandler(streamHandler) + } +} + +func createFilter(request *mgmt_pb.StreamTracesRequest) trace.Filter { + if !request.EnabledFilter { + return trace.NewAllowAllFilter() + } + if request.FilterType == mgmt_pb.TraceFilterType_INCLUDE { + return trace.NewIncludeFilter(request.ContentTypes) + } + return trace.NewExcludeFilter(request.ContentTypes) +} + +type traceEventsHandler struct { + ch channel2.Channel + router trace.EventController + filter trace.Filter +} + +func (handler *traceEventsHandler) Accept(event *trace_pb.ChannelMessage) { + if !handler.filter.Accept(event) { + return + } + body, err := proto.Marshal(event) + if err != nil { + pfxlog.Logger().Errorf("unexpected error unmarshalling ChannelMessage (%s)", err) + return + } + + responseMsg := channel2.NewMessage(int32(mgmt_pb.ContentType_StreamTracesEventType), body) + if err := handler.ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending ChannelMessage (%s)", err) + handler.close() + } +} + +func (handler *traceEventsHandler) close() { + if err := handler.ch.Close(); err != nil { + pfxlog.Logger().WithError(err).Error("unexpected error while closing mgmt channel") + } + handler.router.RemoveHandler(handler) +} diff --git a/fabric/controller/network/assembly.go b/fabric/controller/network/assembly.go new file mode 100644 index 000000000..8017e3f28 --- /dev/null +++ b/fabric/controller/network/assembly.go @@ -0,0 +1,74 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/util/info" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +func (network *Network) assemble() { + log := pfxlog.Logger() + + if network.routerController.count() > 1 { + log.Debugf("assembling with [%d] routers", network.routerController.count()) + + missingLinks, err := network.linkController.missingLinks(network.routerController.all()) + if err == nil { + for _, missingLink := range missingLinks { + network.linkController.add(missingLink) + + dial := &ctrl_pb.Dial{ + Id: missingLink.Id.Token, + Address: missingLink.Dst.AdvertisedListener.String(), + } + bytes, err := proto.Marshal(dial) + if err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_DialType), bytes) + missingLink.Src.Control.Send(msg) + + } else { + log.Errorf("unexpected error (%s)", err) + } + } + + } else { + log.WithField("err", err).Error("missing link enumeration failed") + } + } +} + +func (network *Network) clean() { + log := pfxlog.Logger() + + failedLinks := network.linkController.linksInMode(Failed) + + now := info.NowInMilliseconds() + lRemove := make(map[string]*Link) + for _, l := range failedLinks { + if now-l.CurrentState().Timestamp >= 30000 { + lRemove[l.Id.Token] = l + } + } + for _, lr := range lRemove { + log.Infof("removing [l/%s]", lr.Id.Token) + network.linkController.remove(lr) + } +} diff --git a/fabric/controller/network/circuit.go b/fabric/controller/network/circuit.go new file mode 100644 index 000000000..0d5c4a873 --- /dev/null +++ b/fabric/controller/network/circuit.go @@ -0,0 +1,155 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" +) + +type Circuit struct { + Path []*Router + Links []*Link + Binding string + IngressId string + EgressId string +} + +func (circuit *Circuit) String() string { + if len(circuit.Path) < 1 { + return "{}" + } + if len(circuit.Links) != len(circuit.Path) - 1 { + return "{malformed}" + } + out := fmt.Sprintf("[r/%s]", circuit.Path[0].Id) + for i := 0; i < len(circuit.Links); i++ { + out += fmt.Sprintf("->[l/%s]", circuit.Links[i].Id.Token) + out += fmt.Sprintf("->[r/%s]", circuit.Path[i+1].Id) + } + return out +} + +func (circuit *Circuit) EqualPath(other *Circuit) bool { + if len(circuit.Path) != len(other.Path) { + return false + } + if len(circuit.Links) != len(other.Links) { + return false + } + for i := 0; i < len(circuit.Path); i++ { + if circuit.Path[i] != other.Path[i] { + return false + } + } + for i := 0; i < len(circuit.Links); i++ { + if circuit.Links[i] != other.Links[i] { + return false + } + } + return true +} + +func (circuit *Circuit) EgressRouter() *Router { + if len(circuit.Path) > 0 { + return circuit.Path[len(circuit.Path)-1] + } + return nil +} + +func (circuit *Circuit) CreateRouteMessages(sessionId *identity.TokenId, egressAddress string) ([]*ctrl_pb.Route, error) { + var routeMessages []*ctrl_pb.Route + if len(circuit.Links) == 0 { + // single router path + routeMessage := &ctrl_pb.Route{SessionId: sessionId.Token} + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: circuit.IngressId, + DstAddress: circuit.EgressId, + }) + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: circuit.EgressId, + DstAddress: circuit.IngressId, + }) + routeMessage.Egress = &ctrl_pb.Route_Egress{ + Binding: circuit.Binding, + Address: circuit.EgressId, + Destination: egressAddress, + } + routeMessages = append(routeMessages, routeMessage) + } + + for i, link := range circuit.Links { + if i == 0 { + // ingress + routeMessage := &ctrl_pb.Route{SessionId: sessionId.Token} + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: circuit.IngressId, + DstAddress: link.Id.Token, + }) + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: link.Id.Token, + DstAddress: circuit.IngressId, + }) + routeMessages = append(routeMessages, routeMessage) + } + if i >= 0 && i < len(circuit.Links)-1 { + // transit + nextLink := circuit.Links[i+1] + routeMessage := &ctrl_pb.Route{SessionId: sessionId.Token} + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: link.Id.Token, + DstAddress: nextLink.Id.Token, + }) + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: nextLink.Id.Token, + DstAddress: link.Id.Token, + }) + routeMessages = append(routeMessages, routeMessage) + } + if i == len(circuit.Links)-1 { + // egress + routeMessage := &ctrl_pb.Route{SessionId: sessionId.Token} + routeMessage.Egress = &ctrl_pb.Route_Egress{ + Binding: circuit.Binding, + Address: circuit.EgressId, + Destination: egressAddress, + } + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: circuit.EgressId, + DstAddress: link.Id.Token, + }) + routeMessage.Forwards = append(routeMessage.Forwards, &ctrl_pb.Route_Forward{ + SrcAddress: link.Id.Token, + DstAddress: circuit.EgressId, + }) + routeMessages = append(routeMessages, routeMessage) + } + } + return routeMessages, nil +} + +func (circuit *Circuit) usesLink(l *Link) bool { + if circuit.Links != nil { + for _, o := range circuit.Links { + if o == l { + return true + } + } + } + return false +} diff --git a/fabric/controller/network/circuit_test.go b/fabric/controller/network/circuit_test.go new file mode 100644 index 000000000..861903db8 --- /dev/null +++ b/fabric/controller/network/circuit_test.go @@ -0,0 +1,161 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport/tcp" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSimpleCircuit2(t *testing.T) { + network, err := NewNetwork(nil, nil, nil, nil) + assert.Nil(t, err) + + addr := "tcp:0.0.0.0:0" + transportAddr, err := tcp.AddressParser{}.Parse(addr) + assert.Nil(t, err) + + r0 := newRouter("r0", "", transportAddr, nil) + network.routerController.add(r0) + + r1 := newRouter("r1", "", transportAddr, nil) + network.routerController.add(r1) + + l0 := newLink(&identity.TokenId{Token: "l0"}) + l0.Src = r0 + l0.Dst = r1 + l0.addState(newLinkState(Connected)) + network.linkController.add(l0) + + circuit, err := network.CreateCircuit(r0, r1) + assert.NotNil(t, circuit) + assert.Nil(t, err) + assert.Equal(t, 2, len(circuit.Path)) + assert.Equal(t, r0, circuit.Path[0]) + assert.Equal(t, r1, circuit.Path[1]) + assert.Equal(t, 1, len(circuit.Links)) + assert.Equal(t, l0, circuit.Links[0]) + assert.Equal(t, r1, circuit.EgressRouter()) + + s0 := &identity.TokenId{Token: "s0"} + routeMessages, err := circuit.CreateRouteMessages(s0, addr) + assert.NotNil(t, routeMessages) + assert.Nil(t, err) + assert.Equal(t, 2, len(routeMessages)) + + // ingress route message + rm0 := routeMessages[0] + assert.Equal(t, s0.Token, rm0.SessionId) + assert.Nil(t, rm0.Egress) + assert.Equal(t, 2, len(rm0.Forwards)) + assert.Equal(t, circuit.IngressId, rm0.Forwards[0].SrcAddress) + assert.Equal(t, l0.Id.Token, rm0.Forwards[0].DstAddress) + assert.Equal(t, l0.Id.Token, rm0.Forwards[1].SrcAddress) + assert.Equal(t, circuit.IngressId, rm0.Forwards[1].DstAddress) + + // egress route message + rm1 := routeMessages[1] + assert.Equal(t, s0.Token, rm1.SessionId) + assert.NotNil(t, rm1.Egress) + assert.Equal(t, circuit.EgressId, rm1.Egress.Address) + assert.Equal(t, addr, rm1.Egress.Destination) + assert.Equal(t, circuit.EgressId, rm1.Forwards[0].SrcAddress) + assert.Equal(t, l0.Id.Token, rm1.Forwards[0].DstAddress) + assert.Equal(t, l0.Id.Token, rm1.Forwards[1].SrcAddress) + assert.Equal(t, circuit.EgressId, rm1.Forwards[1].DstAddress) +} + +func TestTransitCircuit2(t *testing.T) { + network, err := NewNetwork(nil, nil, nil, nil) + assert.Nil(t, err) + + addr := "tcp:0.0.0.0:0" + transportAddr, err := tcp.AddressParser{}.Parse(addr) + assert.Nil(t, err) + + r0 := newRouter("r0", "", transportAddr, nil) + network.routerController.add(r0) + + r1 := newRouter("r1", "", transportAddr, nil) + network.routerController.add(r1) + + r2 := newRouter("r2", "", transportAddr, nil) + network.routerController.add(r2) + + l0 := newLink(&identity.TokenId{Token: "l0"}) + l0.Src = r0 + l0.Dst = r1 + l0.addState(newLinkState(Connected)) + network.linkController.add(l0) + + l1 := newLink(&identity.TokenId{Token: "l1"}) + l1.Src = r1 + l1.Dst = r2 + l1.addState(newLinkState(Connected)) + network.linkController.add(l1) + + circuit, err := network.CreateCircuit(r0, r2) + assert.NotNil(t, circuit) + assert.Nil(t, err) + assert.Equal(t, 3, len(circuit.Path)) + assert.Equal(t, r0, circuit.Path[0]) + assert.Equal(t, r1, circuit.Path[1]) + assert.Equal(t, r2, circuit.Path[2]) + assert.Equal(t, 2, len(circuit.Links)) + assert.Equal(t, l0, circuit.Links[0]) + assert.Equal(t, l1, circuit.Links[1]) + assert.Equal(t, r2, circuit.EgressRouter()) + + s0 := &identity.TokenId{Token: "s0"} + routeMessages, err := circuit.CreateRouteMessages(s0, addr) + assert.NotNil(t, routeMessages) + assert.Nil(t, err) + assert.Equal(t, 3, len(routeMessages)) + + // ingress route message + rm0 := routeMessages[0] + assert.Equal(t, s0.Token, rm0.SessionId) + assert.Nil(t, rm0.Egress) + assert.Equal(t, 2, len(rm0.Forwards)) + assert.Equal(t, circuit.IngressId, rm0.Forwards[0].SrcAddress) + assert.Equal(t, l0.Id.Token, rm0.Forwards[0].DstAddress) + assert.Equal(t, l0.Id.Token, rm0.Forwards[1].SrcAddress) + assert.Equal(t, circuit.IngressId, rm0.Forwards[1].DstAddress) + + // transit route message + rm1 := routeMessages[1] + assert.Equal(t, s0.Token, rm1.SessionId) + assert.Nil(t, rm1.Egress) + assert.Equal(t, 2, len(rm1.Forwards)) + assert.Equal(t, l0.Id.Token, rm1.Forwards[0].SrcAddress) + assert.Equal(t, l1.Id.Token, rm1.Forwards[0].DstAddress) + assert.Equal(t, l1.Id.Token, rm1.Forwards[1].SrcAddress) + assert.Equal(t, l0.Id.Token, rm1.Forwards[1].DstAddress) + + // egress route message + rm2 := routeMessages[2] + assert.Equal(t, s0.Token, rm2.SessionId) + assert.NotNil(t, rm2.Egress) + assert.Equal(t, circuit.EgressId, rm2.Egress.Address) + assert.Equal(t, transportAddr.String(), rm2.Egress.Destination) + assert.Equal(t, circuit.EgressId, rm2.Forwards[0].SrcAddress) + assert.Equal(t, l1.Id.Token, rm2.Forwards[0].DstAddress) + assert.Equal(t, l1.Id.Token, rm2.Forwards[1].SrcAddress) + assert.Equal(t, circuit.EgressId, rm2.Forwards[1].DstAddress) +} \ No newline at end of file diff --git a/fabric/controller/network/handler.go b/fabric/controller/network/handler.go new file mode 100644 index 000000000..508c7f2ef --- /dev/null +++ b/fabric/controller/network/handler.go @@ -0,0 +1,22 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +type RouterPresenceHandler interface { + RouterConnected(r *Router) + RouterDisconnected(r *Router) +} diff --git a/fabric/controller/network/link.go b/fabric/controller/network/link.go new file mode 100644 index 000000000..edd2cfd1d --- /dev/null +++ b/fabric/controller/network/link.go @@ -0,0 +1,90 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/info" +) + +type Link struct { + Id *identity.TokenId + Src *Router + Dst *Router + state []*LinkState + Down bool + Cost int + SrcLatency int64 + DstLatency int64 +} + +func newLink(id *identity.TokenId) *Link { + l := &Link{ + Id: id, + state: make([]*LinkState, 0), + Down: false, + Cost: 1, + } + l.addState(&LinkState{Mode: Pending, Timestamp: info.NowInMilliseconds()}) + return l +} + +func (link *Link) CurrentState() *LinkState { + if link.state == nil || len(link.state) < 1 { + return nil + } + return link.state[0] +} + +func (link *Link) addState(s *LinkState) { + if link.state == nil { + link.state = make([]*LinkState, 0) + } + link.state = append([]*LinkState{s}, link.state...) +} + +type LinkMode byte + +const ( + Pending LinkMode = iota + Connected + Failed +) + +func (t LinkMode) String() string { + if t == Pending { + return "Pending" + } else if t == Connected { + return "Connected" + } else if t == Failed { + return "Failed" + } else { + return "" + } +} + +type LinkState struct { + Mode LinkMode + Timestamp int64 +} + +func newLinkState(mode LinkMode) *LinkState { + return &LinkState{ + Mode: mode, + Timestamp: info.NowInMilliseconds(), + } +} diff --git a/fabric/controller/network/link_controller.go b/fabric/controller/network/link_controller.go new file mode 100644 index 000000000..6ea37e558 --- /dev/null +++ b/fabric/controller/network/link_controller.go @@ -0,0 +1,365 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/sequence" + "github.com/orcaman/concurrent-map" + "math" +) + +type linkController struct { + linkTable *linkTable + adjacencyTable *adjacencyTable + sequence *sequence.Sequence +} + +func newLinkController() *linkController { + return &linkController{ + linkTable: newLinkTable(), + adjacencyTable: newAdjacencyTable(), + sequence: sequence.NewSequence(), + } +} + +func (linkController *linkController) add(link *Link) { + linkController.linkTable.add(link) + linkController.adjacencyTable.add(link) +} + +func (linkController *linkController) has(link *Link) bool { + return linkController.linkTable.has(link) +} + +func (linkController *linkController) get(linkId *identity.TokenId) (*Link, bool) { + link, found := linkController.linkTable.get(linkId) + return link, found +} + +func (linkController *linkController) all() []*Link { + return linkController.linkTable.all() +} + +func (linkController *linkController) remove(link *Link) { + linkController.linkTable.remove(link) + linkController.adjacencyTable.remove(link) +} + +func (linkController *linkController) allLinksForRouter(routerId string) []*Link { + if rlt, found := linkController.adjacencyTable.get(routerId); found { + return rlt.allLinksForAllRouters() + } + return nil +} + +func (linkController *linkController) connectedNeighborsOfRouter(router *Router) []*Router { + neighborMap := make(map[string]*Router) + + links := linkController.allLinksForRouter(router.Id) + for _, link := range links { + currentState := link.CurrentState() + if currentState != nil && currentState.Mode == Connected && !link.Down { + if link.Src != router { + neighborMap[link.Src.Id] = link.Src + } + if link.Dst != router { + neighborMap[link.Dst.Id] = link.Dst + } + } + } + + neighbors := make([]*Router, 0) + for _, r := range neighborMap { + neighbors = append(neighbors, r) + } + return neighbors +} + +func (linkController *linkController) leastExpensiveLink(a, b *Router) (*Link, bool) { + var selected *Link + var cost int64 = math.MaxInt64 + + links := linkController.allLinksForRouter(a.Id) + for _, link := range links { + currentState := link.CurrentState() + if currentState != nil && currentState.Mode == Connected && !link.Down { + if link.Src == a && link.Dst == b { + if link.SrcLatency + link.DstLatency < cost { + selected = link + } + } + if link.Dst == a && link.Src == b { + if link.SrcLatency + link.DstLatency < cost { + selected = link + } + } + } + } + + if selected != nil { + return selected, true + } + + return nil, false +} + +func (linkController *linkController) missingLinks(routers []*Router) ([]*Link, error) { + missingLinks := make([]*Link, 0) + for _, srcR := range routers { + for _, dstR := range routers { + if srcR != dstR && dstR.AdvertisedListener != nil { + if _, found := linkController.firstDirectedLink(srcR, dstR); !found { + id, err := linkController.sequence.NextHash() + if err != nil { + return nil, err + } + link := newLink(&identity.TokenId{Token: id}) + link.Src = srcR + link.Dst = dstR + missingLinks = append(missingLinks, link) + } + } + } + } + + return missingLinks, nil +} + +func (linkController *linkController) firstDirectedLink(a, b *Router) (*Link, bool) { + // a->b + if rlt, found := linkController.adjacencyTable.get(a.Id); found { + if links, found := rlt.allLinksForRouter(b.Id); found { + for _, link := range links { + if link.Src == a && link.Dst == b && link.CurrentState().Mode == Connected { + return link, true + } + } + } + } + // b->a + if rlt, found := linkController.adjacencyTable.get(b.Id); found { + if links, found := rlt.allLinksForRouter(a.Id); found { + for _, link := range links { + if link.Src == b && link.Dst == a && link.CurrentState().Mode == Connected { + return link, true + } + } + } + } + return nil, false +} + +func (linkController *linkController) linksInMode(mode LinkMode) []*Link { + return linkController.linkTable.allInMode(mode) +} + +/* + * linkTable + */ + +type linkTable struct { + links cmap.ConcurrentMap // map[Link.Id.Token]*Link +} + +func newLinkTable() *linkTable { + return &linkTable{links: cmap.New()} +} + +func (lt *linkTable) add(link *Link) { + lt.links.Set(link.Id.Token, link) +} + +func (lt *linkTable) get(linkId *identity.TokenId) (*Link, bool) { + link, found := lt.links.Get(linkId.Token) + if link != nil { + return link.(*Link), found + } + return nil, found +} + +func (lt *linkTable) has(link *Link) bool { + if i, found := lt.links.Get(link.Id.Token); found { + if i.(*Link) == link { + return true + } + } + return false +} + +func (lt *linkTable) all() []*Link { + links := make([]*Link, 0) + for i := range lt.links.IterBuffered() { + links = append(links, i.Val.(*Link)) + } + return links +} + +func (lt *linkTable) allInMode(mode LinkMode) []*Link { + links := make([]*Link, 0) + for i := range lt.links.IterBuffered() { + link := i.Val.(*Link) + if link.CurrentState().Mode == mode { + links = append(links, link) + } + } + return links +} + +func (lt *linkTable) remove(link *Link) { + lt.links.Remove(link.Id.Token) +} + +/* + * adjacencyTable + */ + +type adjacencyTable struct { + adjacency cmap.ConcurrentMap // map[Router.Id.Token]*routerLinksTable +} + +func newAdjacencyTable() *adjacencyTable { + return &adjacencyTable{adjacency: cmap.New()} +} + +func (at *adjacencyTable) add(link *Link) { + // src->dst + var rlt *routerLinksTable + if i, found := at.adjacency.Get(link.Src.Id); found { + rlt = i.(*routerLinksTable) + } else { + rlt = newRouterLinksTable() + } + rlt.addLinkForRouter(link.Dst.Id, link) + at.adjacency.Set(link.Src.Id, rlt) + + // dst->src + if i, found := at.adjacency.Get(link.Dst.Id); found { + rlt = i.(*routerLinksTable) + } else { + rlt = newRouterLinksTable() + } + rlt.addLinkForRouter(link.Src.Id, link) + at.adjacency.Set(link.Dst.Id, rlt) +} + +func (at *adjacencyTable) get(routerId string) (*routerLinksTable, bool) { + i, found := at.adjacency.Get(routerId) + if i != nil { + return i.(*routerLinksTable), found + } + return nil, found +} + +func (at *adjacencyTable) remove(link *Link) { + // src->dst + if i, found := at.adjacency.Get(link.Src.Id); found { + rlt := i.(*routerLinksTable) + rlt.removeLinkFromRouter(link.Dst.Id, link) + if rlt.size() > 0 { + at.adjacency.Set(link.Src.Id, rlt) + } else { + at.adjacency.Remove(link.Src.Id) + } + } + + // dst->src + if i, found := at.adjacency.Get(link.Dst.Id); found { + rlt := i.(*routerLinksTable) + rlt.removeLinkFromRouter(link.Src.Id, link) + if rlt.size() > 0 { + at.adjacency.Set(link.Dst.Id, rlt) + } else { + at.adjacency.Remove(link.Dst.Id) + } + } +} + +/* + * routerLinksTable + */ + +type routerLinksTable struct { + routerLinks cmap.ConcurrentMap // map[Router.Id.Token][]*Link +} + +func newRouterLinksTable() *routerLinksTable { + return &routerLinksTable{routerLinks: cmap.New()} +} + +func (rlt *routerLinksTable) addLinkForRouter(routerId string, link *Link) { + var links []*Link + if i, found := rlt.routerLinks.Get(routerId); found { + links = i.([]*Link) + } else { + links = make([]*Link, 0) + } + + links = append(links, link) + rlt.routerLinks.Set(routerId, links) +} + +func (rlt *routerLinksTable) allLinksForRouter(routerId string) ([]*Link, bool) { + if i, found := rlt.routerLinks.Get(routerId); found { + return i.([]*Link), true + } + return nil, false +} + +func (rlt *routerLinksTable) allLinksForAllRouters() []*Link { + linksMap := make(map[string]*Link) + for i := range rlt.routerLinks.IterBuffered() { + links := i.Val.([]*Link) + for _, link := range links { + linksMap[link.Id.Token] = link + } + } + + allLinks := make([]*Link, 0) + for _, v := range linksMap { + allLinks = append(allLinks, v) + } + + return allLinks +} + +func (rlt *routerLinksTable) size() int { + return rlt.routerLinks.Count() +} + +func (rlt *routerLinksTable) removeLinkFromRouter(routerId string, link *Link) { + var links []*Link + if i, found := rlt.routerLinks.Get(routerId); found { + links = i.([]*Link) + if len(links) == 1 && links[0] == link { + rlt.routerLinks.Remove(routerId) + + } else { + i := -1 + for j, jLink := range links { + if jLink == link { + i = j + break + } + } + if i != -1 { + links = append(links[:i], links[i+1:]...) + } + rlt.routerLinks.Set(routerId, links) + } + } +} diff --git a/fabric/controller/network/link_controller_test.go b/fabric/controller/network/link_controller_test.go new file mode 100644 index 000000000..83ef8c189 --- /dev/null +++ b/fabric/controller/network/link_controller_test.go @@ -0,0 +1,73 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestLifecycle(t *testing.T) { + linkController := newLinkController() + + r0 := NewRouter("r0", "") + r1 := NewRouter("r1", "") + l0 := &Link{ + Id: &identity.TokenId{Token: "l0"}, + Src: r0, + Dst: r1, + } + + linkController.add(l0) + assert.True(t, linkController.has(l0)) + + links := linkController.allLinksForRouter(r0.Id) + assert.Equal(t, 1, len(links)) + assert.Equal(t, l0, links[0]) + + links = linkController.allLinksForRouter(r1.Id) + assert.Equal(t, 1, len(links)) + assert.Equal(t, l0, links[0]) + + linkController.remove(l0) + assert.False(t, linkController.has(l0)) + + links = linkController.allLinksForRouter(r0.Id) + assert.Equal(t, 0, len(links)) + + links = linkController.allLinksForRouter(r1.Id) + assert.Equal(t, 0, len(links)) +} + +func TestNeighbors(t *testing.T) { + linkController := newLinkController() + + r0 := newRouter("r0", "", nil, nil) + r1 := newRouter("r1", "", nil, nil) + l0 := &Link{ + Id: &identity.TokenId{Token: "l0"}, + Src: r0, + Dst: r1, + } + l0.addState(newLinkState(Connected)) + linkController.add(l0) + + neighbors := linkController.connectedNeighborsOfRouter(r0) + assert.Equal(t, 1, len(neighbors)) + assert.Equal(t, r1, neighbors[0]) +} diff --git a/fabric/controller/network/network.go b/fabric/controller/network/network.go new file mode 100644 index 000000000..9d5910506 --- /dev/null +++ b/fabric/controller/network/network.go @@ -0,0 +1,637 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-fabric/fabric/controller/db" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-foundation/storage/boltz" + "encoding/json" + "errors" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/concurrenz" + "github.com/netfoundry/ziti-foundation/util/sequence" + "strings" + "sync" + "time" +) + +type Network struct { + nodeId *identity.TokenId + db *db.Db + options *Options + routerController *routerController + routerStore RouterStore + routerChanged chan *Router + linkController *linkController + linkChanged chan *Link + serviceController *serviceController + sessionController *sessionController + sequence *sequence.Sequence + metricsEventController metrics.EventController + sessionLifeCycleController SessionLifeCycleController + traceEventController trace.EventController + traceController trace.Controller + routerPresenceHandlers []RouterPresenceHandler + capabilities []string + shutdownChan chan struct{} + isShutdown concurrenz.AtomicBoolean + lock sync.Mutex +} + +func NewNetwork(nodeId *identity.TokenId, options *Options, db *db.Db, metricsCfg *metrics.Config) (*Network, error) { + serviceController, err := newServiceController(db) + if err != nil { + return nil, err + } + network := &Network{ + nodeId: nodeId, + db: db, + options: options, + routerController: newRouterController(), + routerStore: NewRouterStore(db), + routerChanged: make(chan *Router), + linkController: newLinkController(), + linkChanged: make(chan *Link), + serviceController: serviceController, + sessionController: newSessionController(), + sequence: sequence.NewSequence(), + metricsEventController: metrics.NewEventController(metricsCfg), + sessionLifeCycleController: NewSessionLifeCyleController(), + traceEventController: trace.NewEventController(), + traceController: trace.NewController(), + shutdownChan: make(chan struct{}), + } + network.metricsEventController.AddHandler(network) + network.AddCapability("ziti.fabric") + network.showOptions() + return network, nil +} + +func (network *Network) GetAppId() *identity.TokenId { + return network.nodeId +} + +func (network *Network) GetDb() boltz.Db { + return network.db +} + +func (network *Network) GetRouterStore() RouterStore { + return network.routerStore +} + +func (network *Network) CreateRouter(router *Router) error { + return network.routerStore.create(router) +} + +func (network *Network) GetConnectedRouter(routerId string) (*Router, bool) { + return network.routerController.get(routerId) +} + +func (network *Network) GetRouter(routerId string) (*Router, error) { + return network.routerStore.loadOneById(routerId) +} + +func (network *Network) AllRouters() ([]*Router, error) { + return network.routerStore.all() +} + +func (network *Network) AllConnectedRouters() []*Router { + return network.routerController.all() +} + +func (network *Network) RemoveRouter(router *Router) error { + return network.routerStore.remove(router.Id) +} + +func (network *Network) GetServiceStore() ServiceStore { + return network.serviceController.store +} + +func (network *Network) CreateService(service *Service) error { + return network.serviceController.create(service) +} + +func (network *Network) GetService(serviceId string) (*Service, bool) { + return network.serviceController.get(serviceId) +} + +func (network *Network) AllServices() ([]*Service, error) { + return network.serviceController.all() +} + +func (network *Network) RemoveService(id string) error { + return network.serviceController.remove(id) +} + +func (network *Network) GetLink(linkId *identity.TokenId) (*Link, bool) { + return network.linkController.get(linkId) +} + +func (network *Network) GetAllLinks() []*Link { + return network.linkController.all() +} + +func (network *Network) GetAllLinksForRouter(routerId string) []*Link { + return network.linkController.allLinksForRouter(routerId) +} + +func (network *Network) GetSession(sessionId *identity.TokenId) (*session, bool) { + return network.sessionController.get(sessionId) +} + +func (network *Network) GetAllSessions() []*session { + return network.sessionController.all() +} + +func (network *Network) GetMetricsEventController() metrics.EventController { + return network.metricsEventController +} + +func (network *Network) GetSessionLifeCycleController() SessionLifeCycleController { + return network.sessionLifeCycleController +} + +func (network *Network) GetTraceEventController() trace.EventController { + return network.traceEventController +} + +func (network *Network) GetTraceController() trace.Controller { + return network.traceController +} + +func (network *Network) RouterChanged(r *Router) { + network.routerChanged <- r +} + +func (network *Network) ConnectedRouter(id string) bool { + return network.routerController.has(id) +} + +func (network *Network) KnownRouter(id string) (*Router, error) { + r, err := network.routerStore.loadOneById(id) + if err != nil { + return nil, err + } + return r, nil +} + +func (network *Network) ConnectRouter(r *Router) { + network.routerController.add(r) + network.routerChanged <- r + + for _, h := range network.routerPresenceHandlers { + h.RouterConnected(r) + } +} + +func (network *Network) DisconnectRouter(r *Router) { + // 1: remove Links for Router + for _, l := range network.linkController.allLinksForRouter(r.Id) { + network.linkController.remove(l) + network.LinkChanged(l) + } + // 2: remove Router + network.routerController.remove(r) + network.routerChanged <- r + + for _, h := range network.routerPresenceHandlers { + h.RouterDisconnected(r) + } +} + +func (network *Network) LinkConnected(id *identity.TokenId, connected bool) error { + log := pfxlog.Logger() + + if l, found := network.linkController.get(id); found { + if connected { + l.addState(newLinkState(Connected)) + log.Infof("link [l/%s] connected", id.Token) + return nil + } + l.addState(newLinkState(Failed)) + log.Infof("link [l/%s] failed", id.Token) + return nil + } + return fmt.Errorf("no such link [l/%s]", id.Token) +} + +func (network *Network) LinkChanged(l *Link) { + // This is called from Channel.rxer() and thus may not block + go func() { + network.linkChanged <- l + }() +} + +func (network *Network) BindService(srcR *Router, token string, serviceId string) error { + // 1: Find Service + if svc, found := network.serviceController.get(serviceId); found { + svc.Egress = srcR.Id + svc.EndpointAddress = "hosted:" + token + + return network.serviceController.update(svc) + } + return errors.New("invalid service") +} + +func (network *Network) UnbindService(srcR *Router, token string, serviceId string) error { + // 1: Find Service + if svc, found := network.serviceController.get(serviceId); found { + svc.Egress = network.nodeId.Token // TODO: can't set this to null, so setting it to the controller ID + svc.EndpointAddress = "hosted:unbound" + + return network.serviceController.update(svc) + } + return errors.New("invalid service") +} + +func (network *Network) CreateSession(srcR *Router, clientId *identity.TokenId, serviceId string) (*session, error) { + log := pfxlog.Logger() + + // 1: Find Service + if svc, found := network.serviceController.get(serviceId); found { + // 2: Allocate Session Identifier + sessionIdHash, err := network.sequence.NextHash() + if err != nil { + return nil, err + } + sessionId := &identity.TokenId{Token: sessionIdHash} + + // 3: Get Egress Router + if er, found := network.routerController.get(svc.Egress); found { + // 4: Create Circuit + circuit, err := network.CreateCircuit(srcR, er) + if err != nil { + return nil, err + } + circuit.Binding = "transport" + if svc.Binding != "" { + circuit.Binding = svc.Binding + } else if strings.HasPrefix(svc.EndpointAddress, "hosted") { + circuit.Binding = "edge" + } else if strings.HasPrefix(svc.EndpointAddress, "udp") { + circuit.Binding = "udp" + } + + // 4a: Create Route Messages + rms, err := circuit.CreateRouteMessages(sessionId, svc.EndpointAddress) + if err != nil { + return nil, err + } + + // 5: Route Egress + err = sendRoute(circuit.Path[len(circuit.Path)-1], rms[len(rms)-1]) + if err != nil { + return nil, err + } + + // 6: Create Intermediate Routes + for i := 0; i < len(circuit.Path)-1; i++ { + err = sendRoute(circuit.Path[i], rms[i]) + if err != nil { + return nil, err + } + } + + // 7: Create Session Object + ss := &session{ + Id: sessionId, + ClientId: clientId, + Service: svc, + Circuit: circuit, + } + network.sessionController.add(ss) + network.sessionLifeCycleController.SessionCreated(ss.Id, ss.ClientId, ss.Service.Id, ss.Circuit) + + log.Infof("created session [s/%s] ==> %s", sessionId.Token, ss.Circuit) + + return ss, nil + + } + return nil, errors.New("missing egress") + } + return nil, errors.New("invalid service") +} + +func (network *Network) RemoveSession(sessionId *identity.TokenId, now bool) error { + log := pfxlog.Logger() + + if ss, found := network.sessionController.get(sessionId); found { + for _, r := range ss.Circuit.Path { + err := sendUnroute(r, ss.Id, now) + if err != nil { + log.Errorf("error sending unroute to [r/%s] (%s)", r.Id, err) + } + } + network.sessionController.remove(ss) + network.sessionLifeCycleController.SessionDeleted(sessionId) + + log.Infof("removed session [s/%s]", ss.Id.Token) + + return nil + } + return fmt.Errorf("invalid session (%s)", sessionId.Token) +} + +func (network *Network) StartSessionEgress(sessionId *identity.TokenId) error { + log := pfxlog.Logger() + + if ss, found := network.sessionController.get(sessionId); found { + terminatingRouter := ss.Circuit.Path[len(ss.Circuit.Path)-1] + log.Infof("started session egress [s/%s]", ss.Id.Token) + return sendStartXgress(terminatingRouter, sessionId) + } + return fmt.Errorf("invalid session (%s)", sessionId.Token) +} + +func (network *Network) CreateCircuit(srcR, dstR *Router) (*Circuit, error) { + ingressId, err := network.sequence.NextHash() + if err != nil { + return nil, err + } + + egressId, err := network.sequence.NextHash() + if err != nil { + return nil, err + } + + circuit := &Circuit{ + Links: make([]*Link, 0), + IngressId: ingressId, + EgressId: egressId, + Path: make([]*Router, 0), + } + circuit.Path = append(circuit.Path, srcR) + circuit.Path = append(circuit.Path, dstR) + + return network.UpdateCircuit(circuit) +} + +func (network *Network) UpdateCircuit(circuit *Circuit) (*Circuit, error) { + srcR := circuit.Path[0] + dstR := circuit.Path[len(circuit.Path)-1] + path, err := network.shortestPath(srcR, dstR) + if err != nil { + return nil, err + } + + circuit2 := &Circuit{ + Path: path, + Binding: circuit.Binding, + IngressId: circuit.IngressId, + EgressId: circuit.EgressId, + } + + if len(path) > 1 { + for i := 0; i < len(path)-1; i++ { + if link, found := network.linkController.leastExpensiveLink(path[i], path[i+1]); found { + circuit2.Links = append(circuit2.Links, link) + } + } + } + + return circuit2, nil +} + +func (network *Network) AddRouterPresenceHandler(h RouterPresenceHandler) { + network.routerPresenceHandlers = append(network.routerPresenceHandlers, h) +} + +func (network *Network) Debug() string { + return "oh, wow" +} + +func (network *Network) Run() { + log := pfxlog.Logger() + defer log.Error("exited") + log.Info("started") + + for { + select { + case r := <-network.routerChanged: + log.Infof("changed router [r/%s]", r.Id) + network.assemble() + network.clean() + + case l := <-network.linkChanged: + log.Infof("changed link [l/%s]", l.Id.Token) + if err := network.rerouteLink(l); err != nil { + log.Errorf("unexpected error rerouting link (%s)", err) + } + + case <-time.After(time.Duration(network.options.CycleSeconds) * time.Second): + network.assemble() + network.clean() + network.smart() + case _, ok := <-network.shutdownChan: + if !ok { + return + } + } + } +} + +func (network *Network) Shutdown() { + if network.isShutdown.CompareAndSwap(false, true) { + close(network.shutdownChan) + } +} + +func (network *Network) AddCapability(capability string) { + network.lock.Lock() + defer network.lock.Unlock() + network.capabilities = append(network.capabilities, capability) +} + +func (network *Network) GetCapabilities() []string { + network.lock.Lock() + defer network.lock.Unlock() + return network.capabilities +} + +func (network *Network) rerouteLink(l *Link) error { + log := pfxlog.Logger() + log.Infof("link [l/%s] changed", l.Id.Token) + + sessions := network.sessionController.all() + for _, s := range sessions { + if s.Circuit.usesLink(l) { + log.Infof("session [s/%s] uses link [l/%s]", s.Id.Token, l.Id.Token) + if err := network.rerouteSession(s); err != nil { + log.Errorf("error rerouting session [s/%s], removing", s.Id.Token) + if err := network.RemoveSession(s.Id, true); err != nil { + log.Errorf("error removing session [s/%s] (%s)", s.Id.Token, err) + } + } + } + } + + return nil +} + +func (network *Network) rerouteSession(s *session) error { + log := pfxlog.Logger() + log.Warnf("rerouting [s/%s]", s.Id.Token) + + if cq, err := network.UpdateCircuit(s.Circuit); err == nil { + s.Circuit = cq + + rms, err := cq.CreateRouteMessages(s.Id, s.Service.EndpointAddress) + if err != nil { + log.Errorf("error creating route messages (%s)", err) + return err + } + + for i := 0; i < len(cq.Path); i++ { + if err := sendRoute(cq.Path[i], rms[i]); err != nil { + log.Errorf("error sending route to [r/%s] (%s)", cq.Path[i].Id, err) + } + } + + log.Infof("rerouted session [s/%s]", s.Id.Token) + + network.sessionLifeCycleController.CircuitUpdated(s.Id, s.Circuit) + + return nil + } else { + return err + } +} + +func (network *Network) smartReroute(s *session, cq *Circuit) error { + log := pfxlog.Logger() + + s.Circuit = cq + + rms, err := cq.CreateRouteMessages(s.Id, s.Service.EndpointAddress) + if err != nil { + log.Errorf("error creating route messages (%s)", err) + return err + } + + for i := 0; i < len(cq.Path); i++ { + if err := sendRoute(cq.Path[i], rms[i]); err != nil { + log.Errorf("error sending route to [r/%s] (%s)", cq.Path[i].Id, err) + } + } + + log.Debugf("rerouted session [s/%s]", s.Id.Token) + + network.sessionLifeCycleController.CircuitUpdated(s.Id, s.Circuit) + + return nil +} + +func (network *Network) AcceptMetrics(metrics *ctrl_pb.MetricsMessage) { + log := pfxlog.Logger() + + router, err := network.routerStore.loadOneById(metrics.SourceId) + if err != nil { + log.Warnf("could not find router [r/%s] while processing metrics", metrics.SourceId) + return + } + + for _, link := range network.GetAllLinksForRouter(router.Id) { + metricId := "link." + link.Id.Token + ".latency" + if latency, ok := metrics.Histograms[metricId]; ok { + if link.Src.Id == router.Id { + link.SrcLatency = int64(latency.Mean) + } else if link.Dst.Id == router.Id { + link.DstLatency = int64(latency.Mean) + } else { + log.Warnf("link not for router (wtf?)") + } + } + } +} + +func sendRoute(r *Router, createMsg *ctrl_pb.Route) error { + pfxlog.Logger().Debugf("sending create route message to [r/%s] for [s/%s]", r.Id, createMsg.SessionId) + + body, err := proto.Marshal(createMsg) + if err != nil { + return err + } + + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_RouteType), body) + waitCh, err := r.Control.SendAndWait(msg) + if err != nil { + return err + } + select { + case msg := <-waitCh: + if msg.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(msg) + + if !result.Success { + return errors.New(result.Message) + } + return nil + } + return fmt.Errorf("unexpected response type %v received in reply to route request", msg.ContentType) + + case <-time.After(10 * time.Second): + pfxlog.Logger().Errorf("timed out waiting for response to route message from [r/%s] for [s/%s]", r.Id, createMsg.SessionId) + return errors.New("timeout") + } +} + +func sendUnroute(r *Router, sessionId *identity.TokenId, now bool) error { + remove := &ctrl_pb.Unroute{ + SessionId: sessionId.Token, + Now: now, + } + body, err := proto.Marshal(remove) + if err != nil { + return err + } + removeMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_UnrouteType), body) + if err := r.Control.Send(removeMsg); err != nil { + return err + } + return nil +} + +func sendStartXgress(r *Router, sessionId *identity.TokenId) error { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_StartXgressType), []byte(sessionId.Token)) + if err := r.Control.Send(msg); err != nil { + return err + } + return nil +} + +func (network *Network) showOptions() { + if jsonOptions, err := json.MarshalIndent(network.options, "", " "); err == nil { + pfxlog.Logger().Infof("network = %s", string(jsonOptions)) + } else { + panic(err) + } +} + +func (network *Network) GetServiceCache() Cache { + return network.serviceController +} + +type Cache interface { + RemoveFromCache(id string) +} \ No newline at end of file diff --git a/fabric/controller/network/options.go b/fabric/controller/network/options.go new file mode 100644 index 000000000..1f4076836 --- /dev/null +++ b/fabric/controller/network/options.go @@ -0,0 +1,75 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "errors" + "github.com/michaelquigley/pfxlog" +) + +type Options struct { + CycleSeconds uint32 + Smart struct { + RerouteFraction float32 + RerouteCap uint32 + } +} + +func DefaultOptions() *Options { + options := &Options{ + CycleSeconds: 15, + } + options.Smart.RerouteFraction = 0.02 + options.Smart.RerouteCap = 4 + return options +} + +func LoadOptions(src map[interface{}]interface{}) (*Options, error) { + options := DefaultOptions() + + if value, found := src["cycleSeconds"]; found { + if cycleSeconds, ok := value.(int); ok { + options.CycleSeconds = uint32(cycleSeconds) + } else { + return nil, errors.New("invalid value for 'cycleSeconds'") + } + } + + if value, found := src["smart"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["rerouteFraction"]; found { + if rerouteFraction, ok := value.(float64); ok { + options.Smart.RerouteFraction = float32(rerouteFraction) + } else { + pfxlog.Logger().Errorf("%p", value) + } + } + + if value, found := submap["rerouteCap"]; found { + if rerouteCap, ok := value.(int); ok { + options.Smart.RerouteCap = uint32(rerouteCap) + } else { + pfxlog.Logger().Errorf("%p", value) + } + } + } else { + pfxlog.Logger().Errorf("invalid or empty 'smart' stanza") + } + } + + return options, nil +} diff --git a/fabric/controller/network/path.go b/fabric/controller/network/path.go new file mode 100644 index 000000000..614e391a1 --- /dev/null +++ b/fabric/controller/network/path.go @@ -0,0 +1,105 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "errors" + "math" +) + +func (network *Network) shortestPath(srcR *Router, dstR *Router) ([]*Router, error) { + if srcR == nil || dstR == nil { + return nil, errors.New("not routable (!srcR||!dstR)") + } + + if srcR == dstR { + return []*Router{srcR}, nil + } + + dist := make(map[*Router]int64) + prev := make(map[*Router]*Router) + unvisited := make(map[*Router]bool) + + for _, r := range network.routerController.all() { + dist[r] = math.MaxInt32 + unvisited[r] = true + } + dist[srcR] = 0 + + for len(unvisited) > 0 { + u := minCost(unvisited, dist) + delete(unvisited, u) + + neighbors := network.linkController.connectedNeighborsOfRouter(u) + for _, r := range neighbors { + if _, found := unvisited[r]; found { + cost := int64(r.CostFactor) + if l, found := network.linkController.leastExpensiveLink(r, u); found { + cost += l.SrcLatency + cost += l.DstLatency + } + + alt := dist[u] + cost + if alt < dist[r] { + dist[r] = alt + prev[r] = u + } + } + } + } + + /* + * dist: (r2->r1->r0) + * r0 = 2 <- r1 + * r1 = 1 <- r2 + * r2 = 0 <- nil + */ + + routerPath := make([]*Router, 0) + p := prev[dstR] + for p != nil { + routerPath = append([]*Router{p}, routerPath...) + p = prev[p] + } + routerPath = append(routerPath, dstR) + + if routerPath[0] != srcR { + return nil, errors.New("not routable (~srcR)") + } + if routerPath[len(routerPath)-1] != dstR { + return nil, errors.New("not routable (~dstR)") + } + + return routerPath, nil +} + +func minCost(q map[*Router]bool, dist map[*Router]int64) *Router { + if dist == nil || len(dist) < 1 { + return nil + } + + min := int64(math.MaxInt64) + var selected *Router + for r := range q { + d := dist[r] + if d <= min { + selected = r + min = d + } + } + return selected +} diff --git a/fabric/controller/network/router.go b/fabric/controller/network/router.go new file mode 100644 index 000000000..8c07a4d58 --- /dev/null +++ b/fabric/controller/network/router.go @@ -0,0 +1,89 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/transport" + "github.com/orcaman/concurrent-map" +) + +type Router struct { + Id string + Fingerprint string + AdvertisedListener transport.Address + Control channel2.Channel + CostFactor int +} + +func NewRouter(id, fingerprint string) *Router { + return &Router{ + Id: id, + Fingerprint: fingerprint, + } +} + +func newRouter(id string, fingerprint string, advLstnr transport.Address, ctrl channel2.Channel) *Router { + return &Router{ + Id: id, + Fingerprint: fingerprint, + AdvertisedListener: advLstnr, + Control: ctrl, + CostFactor: 1, + } +} + +type routerController struct { + connected cmap.ConcurrentMap // map[string]*Router +} + +func newRouterController() *routerController { + return &routerController{ + connected: cmap.New(), + } +} + +func (c *routerController) add(r *Router) { + c.connected.Set(r.Id, r) +} + +func (c *routerController) has(id string) bool { + return c.connected.Has(id) +} + +func (c *routerController) get(id string) (*Router, bool) { + if t, found := c.connected.Get(id); found { + return t.(*Router), true + } + return nil, false +} + +func (c *routerController) all() []*Router { + routers := make([]*Router, 0) + for i := range c.connected.IterBuffered() { + routers = append(routers, i.Val.(*Router)) + } + return routers +} + +func (c *routerController) count() int { + return c.connected.Count() +} + +func (c *routerController) remove(r *Router) { + c.connected.Remove(r.Id) +} diff --git a/fabric/controller/network/router_store.go b/fabric/controller/network/router_store.go new file mode 100644 index 000000000..ded82155b --- /dev/null +++ b/fabric/controller/network/router_store.go @@ -0,0 +1,142 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/storage/boltz" + "fmt" + "go.etcd.io/bbolt" +) + +const ( + EntityTypeRouters = "routers" + FieldFingerprint = "fingerprint" +) + +func (router *Router) GetId() string { + return router.Id +} + +func (router *Router) SetId(id string) { + router.Id = id +} + +func (router *Router) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { + router.Fingerprint = bucket.GetStringOrError(FieldFingerprint) +} + +func (router *Router) SetValues(ctx *boltz.PersistContext) { + ctx.SetString(FieldFingerprint, router.Fingerprint) +} + +func (router *Router) GetEntityType() string { + return EntityTypeRouters +} + +type RouterStore interface { + boltz.CrudStore + create(router *Router) error + update(router *Router) error + remove(id string) error + all() ([]*Router, error) + loadOneById(id string) (*Router, error) + LoadOneById(tx *bbolt.Tx, id string) (*Router, error) +} + +func NewRouterStore(db boltz.Db) RouterStore { + notFoundErrorFactory := func(id string) error { + return fmt.Errorf("missing router '%s'", id) + } + + store := &routerStoreImpl{ + db: db, + BaseStore: boltz.NewBaseStore(nil, EntityTypeRouters, notFoundErrorFactory, boltz.RootBucket), + } + store.InitImpl(store) + return store +} + +type routerStoreImpl struct { + db boltz.Db + *boltz.BaseStore +} + +func (store *routerStoreImpl) NewStoreEntity() boltz.BaseEntity { + return &Router{} +} + +func (store *routerStoreImpl) create(router *Router) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.Create(boltz.NewMutateContext(tx), router) + }) +} + +func (store *routerStoreImpl) update(router *Router) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.Update(boltz.NewMutateContext(tx), router, nil) + }) +} + +func (store *routerStoreImpl) remove(id string) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.DeleteById(boltz.NewMutateContext(tx), id) + }) +} + +func (store *routerStoreImpl) loadOneById(id string) (router *Router, err error) { + err = store.db.View(func(tx *bbolt.Tx) error { + router, err = store.LoadOneById(tx, id) + return err + }) + if err != nil { + return nil, err + } + if router == nil { + return nil, fmt.Errorf("missing router '%s'", id) + } + return +} + +func (store *routerStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Router, error) { + router := &Router{} + if found, err := store.BaseLoadOneById(tx, id, router); !found || err != nil { + return nil, err + } + return router, nil +} + +func (store *routerStoreImpl) all() ([]*Router, error) { + routers := make([]*Router, 0) + err := store.db.View(func(tx *bbolt.Tx) error { + ids, _, err := store.QueryIds(tx, "true") + if err != nil { + return err + } + for _, id := range ids { + router, err := store.LoadOneById(tx, string(id)) + if err != nil { + return err + } + routers = append(routers, router) + } + return nil + }) + if err != nil { + return nil, err + } + return routers, nil +} \ No newline at end of file diff --git a/fabric/controller/network/service.go b/fabric/controller/network/service.go new file mode 100644 index 000000000..59c26e8a2 --- /dev/null +++ b/fabric/controller/network/service.go @@ -0,0 +1,91 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-fabric/fabric/controller/db" + "github.com/michaelquigley/pfxlog" + "github.com/orcaman/concurrent-map" +) + +type Service struct { + Id string + Binding string + EndpointAddress string + Egress string +} + +type serviceController struct { + cache cmap.ConcurrentMap + store ServiceStore +} + +func newServiceController(db *db.Db) (*serviceController, error) { + return &serviceController{cache: cmap.New(), store: NewServiceStore(db)}, nil +} + +func (c *serviceController) create(s *Service) error { + err := c.store.create(s) + if err != nil { + return err + } + c.cache.Set(s.Id, s) + return nil +} + +func (c *serviceController) update(s *Service) error { + err := c.store.update(s) + if err != nil { + return err + } + c.cache.Set(s.Id, s) + return nil +} + +func (c *serviceController) get(id string) (*Service, bool) { + if t, found := c.cache.Get(id); found { + return t.(*Service), true + + } + svc, err := c.store.loadOneById(id) + if err != nil { + pfxlog.Logger().Errorf("failed loading service (%s)", err) + return nil, false + } + if svc != nil { + c.cache.Set(svc.Id, svc) + return svc, true + } + return nil, false +} + +func (c *serviceController) all() ([]*Service, error) { + svcs, err := c.store.all() + if err != nil { + return nil, err + } + return svcs, nil +} + +func (c *serviceController) remove(id string) error { + c.cache.Remove(id) + return c.store.remove(id) +} + +func (c *serviceController) RemoveFromCache(id string) { + c.cache.Remove(id) +} \ No newline at end of file diff --git a/fabric/controller/network/service_store.go b/fabric/controller/network/service_store.go new file mode 100644 index 000000000..8e79eb251 --- /dev/null +++ b/fabric/controller/network/service_store.go @@ -0,0 +1,152 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/storage/ast" + "github.com/netfoundry/ziti-foundation/storage/boltz" + "fmt" + "go.etcd.io/bbolt" +) + +const ( + EntityTypeServices = "services" + FieldServiceBinding = "binding" + FieldServiceEndpoint = "endpoint" + FieldServiceEgress = "egress" +) + +func (service *Service) GetId() string { + return service.Id +} + +func (service *Service) SetId(id string) { + service.Id = id +} + +func (service *Service) LoadValues(_ boltz.CrudStore, bucket *boltz.TypedBucket) { + service.Binding = bucket.GetStringWithDefault(FieldServiceBinding, "") + service.EndpointAddress = bucket.GetStringWithDefault(FieldServiceEndpoint, "") + service.Egress = bucket.GetStringWithDefault(FieldServiceEgress, "") +} + +func (service *Service) SetValues(ctx *boltz.PersistContext) { + ctx.SetString(FieldServiceBinding, service.Binding) + ctx.SetString(FieldServiceEndpoint, service.EndpointAddress) + ctx.SetString(FieldServiceEgress, service.Egress) +} + +func (service *Service) GetEntityType() string { + return EntityTypeServices +} + +type ServiceStore interface { + boltz.CrudStore + create(service *Service) error + update(svc *Service) error + remove(id string) error + all() ([]*Service, error) + loadOneById(id string) (*Service, error) + LoadOneById(tx *bbolt.Tx, id string) (*Service, error) +} + +func NewServiceStore(db boltz.Db) ServiceStore { + notFoundErrorFactory := func(id string) error { + return fmt.Errorf("missing service '%s'", id) + } + + store := &serviceStoreImpl{ + db: db, + BaseStore: boltz.NewBaseStore(nil, EntityTypeServices, notFoundErrorFactory, boltz.RootBucket), + } + store.InitImpl(store) + store.AddSymbol(FieldServiceBinding, ast.NodeTypeString) + store.AddSymbol(FieldServiceEndpoint, ast.NodeTypeString) + store.AddSymbol(FieldServiceEgress, ast.NodeTypeString) + return store +} + +type serviceStoreImpl struct { + db boltz.Db + *boltz.BaseStore +} + +func (store *serviceStoreImpl) NewStoreEntity() boltz.BaseEntity { + return &Service{} +} + +func (store *serviceStoreImpl) create(service *Service) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.Create(boltz.NewMutateContext(tx), service) + }) +} + +func (store *serviceStoreImpl) update(service *Service) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.Update(boltz.NewMutateContext(tx), service, nil) + }) +} + +func (store *serviceStoreImpl) remove(id string) error { + return store.db.Update(func(tx *bbolt.Tx) error { + return store.DeleteById(boltz.NewMutateContext(tx), id) + }) +} + +func (store *serviceStoreImpl) loadOneById(id string) (service *Service, err error) { + err = store.db.View(func(tx *bbolt.Tx) error { + service, err = store.LoadOneById(tx, id) + return err + }) + if err != nil { + return nil, err + } + if service == nil { + return nil, fmt.Errorf("missing service '%s'", id) + } + return +} + +func (store *serviceStoreImpl) LoadOneById(tx *bbolt.Tx, id string) (*Service, error) { + service := &Service{} + if found, err := store.BaseLoadOneById(tx, id, service); !found || err != nil { + return nil, err + } + return service, nil +} + +func (store *serviceStoreImpl) all() ([]*Service, error) { + services := make([]*Service, 0) + err := store.db.View(func(tx *bbolt.Tx) error { + ids, _, err := store.QueryIds(tx, "true") + if err != nil { + return err + } + for _, id := range ids { + service, err := store.LoadOneById(tx, string(id)) + if err != nil { + return err + } + services = append(services, service) + } + return nil + }) + if err != nil { + return nil, err + } + return services, nil +} \ No newline at end of file diff --git a/fabric/controller/network/session.go b/fabric/controller/network/session.go new file mode 100644 index 000000000..4a54a8fa5 --- /dev/null +++ b/fabric/controller/network/session.go @@ -0,0 +1,88 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/orcaman/concurrent-map" +) + +type session struct { + Id *identity.TokenId + ClientId *identity.TokenId + Service *Service + Circuit *Circuit +} + +func (s *session) latency() int64 { + var latency int64 + for _, l := range s.Circuit.Links { + latency += l.SrcLatency + latency += l.DstLatency + } + return latency +} + +type sessionController struct { + sessions cmap.ConcurrentMap // map[string]*Session + sessionsByService cmap.ConcurrentMap // map[string]*Sessions +} + +func newSessionController() *sessionController { + return &sessionController{ + sessions: cmap.New(), + sessionsByService: cmap.New(), + } +} + +func (c *sessionController) add(sn *session) { + c.sessions.Set(sn.Id.Token, sn) + + if !c.sessionsByService.Has(sn.Service.Id) { + c.sessionsByService.Set(sn.Service.Id, cmap.New()) + } + t, _ := c.sessionsByService.Get(sn.Service.Id) + sessionsForService := t.(cmap.ConcurrentMap) + sessionsForService.Set(sn.Id.Token, sn) +} + +func (c *sessionController) get(id *identity.TokenId) (*session, bool) { + if t, found := c.sessions.Get(id.Token); found { + return t.(*session), true + } + return nil, false +} + +func (c *sessionController) all() []*session { + sessions := make([]*session, 0) + for i := range c.sessions.IterBuffered() { + sessions = append(sessions, i.Val.(*session)) + } + return sessions +} + +func (c *sessionController) remove(sn *session) { + c.sessions.Remove(sn.Id.Token) + + if t, found := c.sessionsByService.Get(sn.Service.Id); found { + sessionsForService := t.(cmap.ConcurrentMap) + sessionsForService.Remove(sn.Id.Token) + if sessionsForService.Count() < 1 { + c.sessionsByService.Remove(sn.Service.Id) + } + } +} diff --git a/fabric/controller/network/session_lifecycle.go b/fabric/controller/network/session_lifecycle.go new file mode 100644 index 000000000..fc06d4c67 --- /dev/null +++ b/fabric/controller/network/session_lifecycle.go @@ -0,0 +1,165 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type SessionLifeCycleListener interface { + SessionCreated(sessionId *identity.TokenId, clientId *identity.TokenId, serviceId string, circuit *Circuit) + SessionDeleted(sessionId *identity.TokenId) + CircuitUpdated(sessionId *identity.TokenId, circuit *Circuit) +} + +// SessionLifeCycleController allows for sending session changes to multiple Listeners +type SessionLifeCycleController interface { + SessionLifeCycleListener + + // AddListener adds the given listener to the controller + AddListener(listener SessionLifeCycleListener) + + // RemoveListener removes the given listener from the controller + RemoveListener(listener SessionLifeCycleListener) + + // Shutdown stops the controller + Shutdown() +} + +// NewSessionLifeCycleController creates a new SessionLifeCycleController instance +func NewSessionLifeCyleController() SessionLifeCycleController { + controller := &sessionLifeCycleControllerImpl{ + changeChan: make(chan sessionLifeCycleControllerChange, 1), + eventChan: make(chan sessionLifeCycleEvent, 25), + listeners: make(map[SessionLifeCycleListener]SessionLifeCycleListener), + } + + go controller.run() + return controller +} + +type sessionLifeCycleControllerImpl struct { + changeChan chan sessionLifeCycleControllerChange + eventChan chan sessionLifeCycleEvent + listeners map[SessionLifeCycleListener]SessionLifeCycleListener +} + +func (controller *sessionLifeCycleControllerImpl) SessionCreated(sessionId *identity.TokenId, clientId *identity.TokenId, serviceId string, circuit *Circuit) { + event := &sessionCreatedEvent{ + sessionId: sessionId, + clientId: clientId, + serviceId: serviceId, + circuit: circuit, + } + controller.eventChan <- event +} + +func (controller *sessionLifeCycleControllerImpl) SessionDeleted(sessionId *identity.TokenId) { + event := &sessionDeletedEvent{ + sessionId: sessionId, + } + controller.eventChan <- event +} + +func (controller *sessionLifeCycleControllerImpl) CircuitUpdated(sessionId *identity.TokenId, circuit *Circuit) { + event := &sessionCircuitEvent{ + sessionId: sessionId, + circuit: circuit, + } + controller.eventChan <- event +} + +func (controller *sessionLifeCycleControllerImpl) AddListener(listener SessionLifeCycleListener) { + controller.changeChan <- sessionLifeCycleControllerChange{listener, sessionLifeCycleControllerAddListener} +} + +func (controller *sessionLifeCycleControllerImpl) RemoveListener(listener SessionLifeCycleListener) { + controller.changeChan <- sessionLifeCycleControllerChange{listener, sessionLifeCycleControllerRemoveListener} +} + +func (controller *sessionLifeCycleControllerImpl) Shutdown() { + controller.changeChan <- sessionLifeCycleControllerChange{nil, sessionLifeCycleControllerShutdown} +} + +func (controller *sessionLifeCycleControllerImpl) run() { + running := true + for running { + select { + case change := <-controller.changeChan: + if sessionLifeCycleControllerAddListener == change.changeType { + controller.listeners[change.listener] = change.listener + } else if sessionLifeCycleControllerRemoveListener == change.changeType { + delete(controller.listeners, change.listener) + } else if sessionLifeCycleControllerShutdown == change.changeType { + running = false + } + case event := <-controller.eventChan: + event.handle(controller) + } + } +} + +type sessionLifecycleControllerChangeType uint8 + +const ( + sessionLifeCycleControllerAddListener = iota + sessionLifeCycleControllerRemoveListener + sessionLifeCycleControllerShutdown +) + +type sessionLifeCycleControllerChange struct { + listener SessionLifeCycleListener + changeType sessionLifecycleControllerChangeType +} + +type sessionLifeCycleEvent interface { + handle(controller *sessionLifeCycleControllerImpl) +} + +type sessionCreatedEvent struct { + sessionId *identity.TokenId + clientId *identity.TokenId + serviceId string + circuit *Circuit +} + +func (event *sessionCreatedEvent) handle(controller *sessionLifeCycleControllerImpl) { + for _, handler := range controller.listeners { + go handler.SessionCreated(event.sessionId, event.clientId, event.serviceId, event.circuit) + } +} + +type sessionDeletedEvent struct { + sessionId *identity.TokenId +} + +func (event *sessionDeletedEvent) handle(controller *sessionLifeCycleControllerImpl) { + for _, handler := range controller.listeners { + go handler.SessionDeleted(event.sessionId) + } +} + +type sessionCircuitEvent struct { + sessionId *identity.TokenId + circuit *Circuit +} + +func (event *sessionCircuitEvent) handle(controller *sessionLifeCycleControllerImpl) { + for _, handler := range controller.listeners { + go handler.CircuitUpdated(event.sessionId, event.circuit) + } +} \ No newline at end of file diff --git a/fabric/controller/network/smart.go b/fabric/controller/network/smart.go new file mode 100644 index 000000000..ea6427d03 --- /dev/null +++ b/fabric/controller/network/smart.go @@ -0,0 +1,89 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package network + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/michaelquigley/pfxlog" + "sort" +) + +func (network *Network) smart() { + log := pfxlog.Logger() + log.Debugf("smart network processing") + + /* + * Order sessions in decreasing overall latency order + */ + sessions := network.GetAllSessions() + log.Debugf("observing [%d] sessions", len(sessions)) + + sessionLatencies := make(map[*identity.TokenId]int64) + var orderedSessions []*identity.TokenId + for _, s := range sessions { + sessionLatencies[s.Id] = s.latency() + orderedSessions = append(orderedSessions, s.Id) + } + + sort.SliceStable(orderedSessions, func(i, j int) bool { + iId := orderedSessions[i] + jId := orderedSessions[j] + return sessionLatencies[jId] < sessionLatencies[iId] + }) + /* */ + + /* + * Develop candidates for rerouting. + */ + newCircuits := make(map[*session]*Circuit) + var candidates []*session + count := 0 + ceiling := int(float32(len(sessions)) * network.options.Smart.RerouteFraction) + if ceiling < 1 { + ceiling = 1 + } + if ceiling > int(network.options.Smart.RerouteCap) { + ceiling = int(network.options.Smart.RerouteCap) + } + log.Debugf("smart reroute ceiling [%d]", ceiling) + for _, sId := range orderedSessions { + if session, found := network.GetSession(sId); found { + if updatedCircuit, err := network.UpdateCircuit(session.Circuit); err == nil { + if !updatedCircuit.EqualPath(session.Circuit) { + if count < ceiling { + count++ + candidates = append(candidates, session) + newCircuits[session] = updatedCircuit + log.Infof("rerouting [s/%s] [l:%d] %s ==> %s", session.Id.Token, sessionLatencies[session.Id], session.Circuit.String(), updatedCircuit.String()) + } + } + } + } + } + /* */ + + /* + * Reroute. + */ + for _, session := range candidates { + if err := network.smartReroute(session, newCircuits[session]); err != nil { + log.Errorf("error rerouting [s/%s] (%s)", session.Id.Token, err) + } + } + /* */ +} + diff --git a/fabric/ctrl_msg/messages.go b/fabric/ctrl_msg/messages.go new file mode 100644 index 000000000..b50f9d18a --- /dev/null +++ b/fabric/ctrl_msg/messages.go @@ -0,0 +1,38 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package ctrl_msg + +import ( + "github.com/netfoundry/ziti-foundation/channel2" +) + +const ( + ContentTypeSessionSuccessType = 1001 + ContentTypeSessionFailedType = 1016 + + SessionSuccessAddressHeader = 1100 +) + +func NewSessionSuccessMsg(sessionId, address string) *channel2.Message { + msg := channel2.NewMessage(ContentTypeSessionSuccessType, []byte(sessionId)) + msg.Headers[SessionSuccessAddressHeader] = []byte(address) + return msg +} + +func NewSessionFailedMsg(message string) *channel2.Message { + return channel2.NewMessage(ContentTypeSessionFailedType, []byte(message)) +} diff --git a/fabric/doc/p12_smart_routing.md b/fabric/doc/p12_smart_routing.md new file mode 100644 index 000000000..13ee291bb --- /dev/null +++ b/fabric/doc/p12_smart_routing.md @@ -0,0 +1,52 @@ +# Phase 12: Smart Routing 1 + +Ziti Fabric 0.4 includes an initial, experimental implementation of "smart routing". + +Smart routing continually measures the latency between established links in the overlay mesh. The latency data is used in these ways: + +1. When establishing a "circuit" ("path" across the mesh) for a new session, the current latency data is used as a component of the overall "cost" of each candidate path. The cost is fed into the shortest path computation, which uses that data to select the least expensive path across the mesh. So, when new sessions are created, they're given the current least expensive path across the mesh. + +2. The controller periodically scans the network, looking for the sessions experiencing the highest amount of latency. A portion of the sessions with the most latency have new paths computed, and if a session's newly-computed path is different then its current path, that session will be dynamically "optimized" onto the new path. + +This is an experimental implementation. It _should_ result in relatively balanced network utilization, along with some amount of the active network sessions experiencing better then average performance. These algorithms need testing and feedback from real world workloads. + +Keep in mind that the "cost" attribute on each link is user-settable (see the `ziti-fabric link set-cost` tool), and will be added to the link cost considered by the controller. By smart utilization of the link cost, you can directly influence the decisions made by the smart routing algorithms. + +Setting the link cost will provoke the controller to immediately re-consider the routes for each of the sessions currently traversing the adjusted link. If better paths are available for those sessions, they will be re-routed. + +## Network Scaling + +This style of smart routing is intended to dovetail with a scaling strategy where additional network capacity (routers) is spun up and made available as the network workload increases. Smart routing will see the new, non-latent capacity and begin redirecting traffic to it, re-balancing the network. + +There are quite a number of different strategies that are possible for selecting locations to site additional mesh capacity. The work around exploring and understanding those strategies needs to be coordinated with the design of the smart routing and network optimization algorithms present in Ziti. The "fablab" project currently exists to create tooling and infrastructure to explore these kinds of scenarios. We also encourage you to experiment. + +As overall network volume decreases, the additional capacity can be removed from the overlay mesh, and smart routing will again optimize the sessions to best take advantage of performance available in the mesh topology. + +## Configuration + +There are a couple of configuration settings for tuning how smart routing behaves on your network: + + network: + cycleSeconds: 15 + smart: + rerouteFraction: 0.02 + rerouteCap: 4 + +The above stanza goes into your controller's YAML configuration file. + +The `cycleSeconds` parameter controls how frequently the controller will scan the network, looking for active sessions to be optimized. + +The `rerouteFraction` parameter controls the fraction of the total number of sessions to be considered for optimization. The sessions are scanned in descending order of their overall latency, and the worst `rerouteFraction` will be considered. + +The `rerouteCap` parameter defines the upper limit on the total number of sessions to be considered for optimization, even if `rerouteFraction` would select more sessions. This allows an overall cap to set on the number of sessions to be optimized. + +By tuning the controller scan cycle rate (`cycleSeconds`), you can control how frequently your network will be optimized. This is the primary configuration control, which determines how quickly the smart routing algorithms will respond to changing network weather. This performance will need to be balanced against controller CPU burn, and the additional control plane bandwidth required to implement the changing session routing. + +The current implementation is missing a configuration setting, which determines how frequently latency probes are performed on the overlay mesh links. Latency probes are currently performed on 10 second intervals. There probably is not much point in reducing `network.cycleSeconds` below `10`, until the latency probe interval can be configured. We expect this, along with other additional configuation settings, will be available very soon. + +## What's Next? + +Research for the next version of these algorithms is currently underway. We expect the next iteration to include cost considerations and targets around bandwidth metrics. + +We would love your feedback. Please let us know how our current smart routing implementation performs on your real world workloads. If you have ideas for additional capabilities, please let us know! + diff --git a/fabric/etc/001.yml b/fabric/etc/001.yml new file mode 100644 index 000000000..48c00713c --- /dev/null +++ b/fabric/etc/001.yml @@ -0,0 +1,56 @@ +v: 2 + +identity: + cert: fabric/etc/ca/intermediate/certs/001-client.cert.pem + server_cert: fabric/etc/ca/intermediate/certs/001-server.cert.pem + key: fabric/etc/ca/intermediate/private/001.key.pem + ca: fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +# Configure the forwarder options +# +forwarder: + # How frequently does the forwarder probe the link latency. This will ultimately determine the resolution of the + # responsiveness available to smart routing. This resolution comes at the expense of bandwidth utilization for the + # probes, control plane utilization, and CPU utilization processing the results. + # + latencyProbeInterval: 1000 + +#trace: +# path: 001.trace + +#profile: +# memory: +# path: 001.memprof +# cpu: +# path: 001.cpuprof + +ctrl: + endpoint: tls:127.0.0.1:6262 + +listeners: + - binding: proxy + address: tcp:0.0.0.0:1122 + service: ssh + + - binding: proxy + address: tcp:0.0.0.0:10001 + service: mgmt + + - binding: transport + address: tls:0.0.0.0:7001 + options: + retransmission: true + randomDrops: true + drop1InN: 5000 + + - binding: udp + address: udp:0.0.0.0:7002 + options: + retransmission: true + randomDrops: true + drop1InN: 5000 + +# xctrl_example +# +#example: +# delay: 1 diff --git a/fabric/etc/002.yml b/fabric/etc/002.yml new file mode 100644 index 000000000..c26db1849 --- /dev/null +++ b/fabric/etc/002.yml @@ -0,0 +1,21 @@ +v: 2 + +identity: + cert: fabric/etc/ca/intermediate/certs/002-client.cert.pem + server_cert: fabric/etc/ca/intermediate/certs/002-server.cert.pem + key: fabric/etc/ca/intermediate/private/002.key.pem + ca: fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +#trace: +# path: 002.trace + +ctrl: + endpoint: tls:127.0.0.1:6262 + +link: + listener: quic:127.0.0.1:6002 + +listeners: + - binding: transport + address: tls:0.0.0.0:7002 # make sure we don't conflict with router 001 + diff --git a/fabric/etc/003.yml b/fabric/etc/003.yml new file mode 100644 index 000000000..8886bed2c --- /dev/null +++ b/fabric/etc/003.yml @@ -0,0 +1,34 @@ +v: 2 + +identity: + cert: fabric/etc/ca/intermediate/certs/003-client.cert.pem + server_cert: fabric/etc/ca/intermediate/certs/003-server.cert.pem + key: fabric/etc/ca/intermediate/private/003.key.pem + ca: fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +# Configure the forwarder options +# +forwarder: + # How frequently does the forwarder probe the link latency. This will ultimately determine the resolution of the + # responsiveness available to smart routing. This resolution comes at the expense of bandwidth utilization for the + # probes, control plane utilization, and CPU utilization processing the results. + # + latencyProbeInterval: 1000 + +#trace: +# path: 003.trace + +#profile: +# memory: +# path: 003.memprof +# intervalMs: 5000 + +ctrl: + endpoint: tls:127.0.0.1:6262 + +dialers: + - binding: transport + options: + retransmission: true + randomDrops: false + drop1InN: 5000 diff --git a/fabric/etc/004.yml b/fabric/etc/004.yml new file mode 100644 index 000000000..2f2c83880 --- /dev/null +++ b/fabric/etc/004.yml @@ -0,0 +1,25 @@ +v: 2 + +identity: + cert: fabric/etc/ca/intermediate/certs/004-client.cert.pem + server_cert: fabric/etc/ca/intermediate/certs/004-server.cert.pem + key: fabric/etc/ca/intermediate/private/004.key.pem + ca: fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +# Configure the forwarder options +# +forwarder: + # How frequently does the forwarder probe the link latency. This will ultimately determine the resolution of the + # responsiveness available to smart routing. This resolution comes at the expense of bandwidth utilization for the + # probes, control plane utilization, and CPU utilization processing the results. + # + latencyProbeInterval: 1000 + +#trace: +# path: 004.trace + +ctrl: + endpoint: tls:127.0.0.1:6262 + +link: + listener: quic:127.0.0.1:6004 diff --git a/fabric/etc/ca/certs/ca.cert.pem b/fabric/etc/ca/certs/ca.cert.pem new file mode 100644 index 000000000..b88e35a34 --- /dev/null +++ b/fabric/etc/ca/certs/ca.cert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGFjCCA/6gAwIBAgIJAOq4qnKYsnlbMA0GCSqGSIb3DQEBCwUAMIGXMQswCQYD +VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExEjAQBgNVBAcMCUNoYXJs +b3R0ZTETMBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UECwwgTmV0Rm91bmRyeSBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMEk5ldEZvdW5kcnkgUm9vdCBD +QTAeFw0xODA1MTgxNjU0NDdaFw0zODA1MTMxNjU0NDdaMIGXMQswCQYDVQQGEwJV +UzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExEjAQBgNVBAcMCUNoYXJsb3R0ZTET +MBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMEk5ldEZvdW5kcnkgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqr9dr7vj0KvdYkZgMMgS00ohGd +MVzpN6JFKb87uEbb7U2uH905uNkm4OOyilY/w0UD8PCU3ISmFgoB5LAcOa77icV3 +qJ+h4MTaVirps2EtyA34DcyU3k+Fvauc7fZhhnAdcZai/6O13aBorR9awfwJDGfq +fa/uq88xN5gU/yniOpNnDZu9lbD4sxhMULLnjUMWpAtBqwyDXSZdEBVc7s5r3L4P +Wt7XMurjBLq7wi0mgrN+a9mQy8P3QL+1Di7SIlovsYHZIT0w48N4ZW+mehIAiRJW +a9ENQCPbH0+66TKTOgvU4BbNzkKD7kvFGYt6NUTs+89wdpO01qDa1EPDa9sx4Uo3 +w29AfVBhxo9Zl7hWX1voMC5NoflE33X0f8X5kfKNnJtU/ALXiV+Wd4grI3LwkRX9 +gwhsQANae6J53MN6GTY6mf7T71mvZf/F+MKjyJYcVs1pWdBfvB1Fo6jvzeUSi6dy +p7joUMEsGnIC4ModCkhPcwryuQL/XIE3Gwfji8zB5Rm4rS7s8L0oe2alB+5+VgZ/ +EDfiRjpZTePPJAd62gtiOjFOo0QSO4anDLajWPtFoIEQUhtiWeVuGkRYVNpB/3rP +YZDqbVTfLsnIN+UdK70WjUk2QbepeyMPB1r/pbs1ElGB0WuGc7CubsXov1fg/Uef +NT9UkvrovA+aIdWNAgMBAAGjYzBhMB0GA1UdDgQWBBRB8+kUbjrl49psAMznlIp3 +1nor6TAfBgNVHSMEGDAWgBRB8+kUbjrl49psAMznlIp31nor6TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAJ9TvhopZ +E5rGe57y1lvk8WQRucNFxGspdGGem0DS+uAHjJ2djFf2EQFkPyjo8HLet7C+XmZ5 +I4ETrPJvgkPzSUd3MdJUUjBvOw054SMKyW/88D/dj4nsMK3qA80wN5i4Syx2p5KI +yhjPaCe96fh+VIwqBMAl3f9KlWuffkfNeJT0ySYVWk8QydNy06PD4mdwKQbn4P03 +Xh3G2Bn+1R9sf4ZR+HIZXFF0+tfkpCoDJqkx8Roxddrwo2zs8b6wOJJYj5KD2NQa +3GCR8p1U20Vb5AxfLLt5PeJc8D7WvaEUCGB8hoa0ElSHE8cyEq2NsCABf7r7YPcY +BtoPX6VxAeEqvLeHKBDc5fv0UlbrPI9LS2JX8t+i8epf/fH2rk9NUE7AQ5Lb8sJz +hHYztL4cg9/h5In6cfi4Ih0njZYKuiv+ZGy4vuB4KSyLvQYe4LKc/jKpAWzO79S1 +sESw3yWhOcuk4ifFoYHVjxQ+bXhvYujX/ceSgxWHT9RocnROadnWvuZ8aF9HIBlh +F29PWwH4RvhvkDbMRmqxNz0jAU6GcjhmKU+hnmzbF6OqtXDcZK+i8SF2mutCa/G6 +H5VDbfL/7/jP1vbFbIO7bNW94HjCGo97auSDEmsSXgZ8uTYNb503qPzdmXiU+hRl +jDOQLqtoJofIWUChpNurPQfqu9UljEk9LpQ= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/index.txt b/fabric/etc/ca/index.txt new file mode 100644 index 000000000..a1f99f218 --- /dev/null +++ b/fabric/etc/ca/index.txt @@ -0,0 +1 @@ +V 280515165723Z 1000 unknown /C=US/ST=North Carolina/O=NetFoundry/OU=NetFoundry Certificate Authority/CN=NetFoundry Intermediate CA diff --git a/fabric/etc/ca/index.txt.attr b/fabric/etc/ca/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/fabric/etc/ca/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/fabric/etc/ca/index.txt.old b/fabric/etc/ca/index.txt.old new file mode 100644 index 000000000..e69de29bb diff --git a/fabric/etc/ca/intermediate/certs/001-client.cert.pem b/fabric/etc/ca/intermediate/certs/001-client.cert.pem new file mode 100644 index 000000000..89552507f --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/001-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA0wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5Mjg0MFoX +DTI4MDgxMDE5Mjg0MFowczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDbqcpLyr/yZFw2YxOy1RKhO/jw4ra8Z15KdEHN +bz5hcNlT6dmVFQj4sBW9AsB06ynqzrO5cKjnWF/LZXzTRGlDUmxmKZOZCcb4NVy/ +4fwWNN8IBuJQBrrz1qTMBJaG4DRbZ+zTICrb2EJGJyNFZbNKvlRQzn4xMjMm57Up +v2enImy8BHUWahjkcCG/uXPTJzjupTweRI34DPxTU2q3hH7zwocdFMe/mkzShMb1 +qwj33BByHWzSK60NawE140li24v3ELLhre/C6cZSV1Nyk4U9jreSeaQ/uj5cmk08 +dPnCeBcTqMIwhAOihMYM3vqhOZbNfssr7gXd0/8bv/7P6JGpAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAmPpB0t/nGnpJ8zS01256g0P1UjwI +GOj8DF4XhQVChDk+9VYEg1DIvku52m1F7Wxgp8q2ELTEjnywZrK/VD4sos0cWuID +f4DYsUqdM8gGHc5uVY/eubWtcWAo7qegrfdq+S6MD8DqdiCnBTe5xruWBaZhm9aP +lwPpVSqDVTGyjV9wLB/mNc0xOEYg0fenS0UbHZAlDWHHCZQmkMnW1bU07qxKfu0i +/1Ok0H0w/kEIxv6LuSSxPJQ9yvy9eB+2HypdeQl4kuZzue/tXrLn20MhWHPaJZjr +BUDcLYg7Badd2lyySh4T5eSY1XyEPogHCx8XMWRixjkaWgdZpriVgf1g7wXc6W6G +fD9pxQyQ1pq3zL9rbWWzyrmp4gwOsAOq1HwmGJtHI9qVU3VxSrbZCF9bnYTRdIpS +UNWMqOv5uuYspKzcYl2FFdGUd3QQ5ExSsFRZ2+xjfDyhlPOOuJtb3RK3HoY35Gjg +DWB3mU331H+UtCE8oCs5nKQcS0iH86D+CnqJkkvQHSVH+QV4JU202x+Ym0q3aaqy +AuE5Nj5ybnrN/WsL3YYkpbIYZAvGWnvHGYOLjs7caLBwv2vcfibAsPX4m+OhJfuU +0zCzTCS6fzf/Jg9R1p7392CESYfJ34eVuda7ctWZrMXFyGsxeydCO2TTdDjRolO/ +tToiRRetrmH3JcY= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/001-server.cert.pem b/fabric/etc/ca/intermediate/certs/001-server.cert.pem new file mode 100644 index 000000000..0087b7943 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/001-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAkwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjcyNVoX +DTI4MDgxMDE5MjcyNVowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDEtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA26nKS8q/8mRcNmMTstUSoTv48OK2 +vGdeSnRBzW8+YXDZU+nZlRUI+LAVvQLAdOsp6s6zuXCo51hfy2V800RpQ1JsZimT +mQnG+DVcv+H8FjTfCAbiUAa689akzASWhuA0W2fs0yAq29hCRicjRWWzSr5UUM5+ +MTIzJue1Kb9npyJsvAR1FmoY5HAhv7lz0yc47qU8HkSN+Az8U1Nqt4R+88KHHRTH +v5pM0oTG9asI99wQch1s0iutDWsBNeNJYtuL9xCy4a3vwunGUldTcpOFPY63knmk +P7o+XJpNPHT5wngXE6jCMIQDooTGDN76oTmWzX7LK+4F3dP/G7/+z+iRqQIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAInGp9pJYVCUJErrsart +M5vtK/Mm2qBpbpcdj8Gnokh3ubL5rY0MjpOz5AWj0c4wFgV28EdAncjXEor4VOEI +JgsbTm3STNJnA9BT7vAwNezbl1N6jOTh8vUrjaSx5AsWVbah6nZX8rfc9db/m+zd +iYedN0VJF9Fi6wrK2CssDkbYc6PNrK/lhgyWAcacQdthZTWmqmObNToAY1FNk6m0 +OHXW0ipuRFqNRUw6snU9+SqbcOnCqKtpAan+YfNj8cXuiytjxGfQVpQVsp9zdXqX +efkc13iKcJ46GLkWcWrjWKkVt3EjUbaWENECmz4/Nd1LgzmEaTwVUCxtAlVnKk7P +oW5dgJQpWk5chP0XidyvwiKf2iC/fck+drj7f+iJDd26pZ1LFvlA7MO9eYu5HpWQ +tL4dF2MnubU98Hg3m/ryygLZh7I2rvPsx8/g1m8LYhiJ4QFkXKdZ8IQ1daqUtUmr +ooH++0C6r9fNgyEbhGMungcC5DHP58CofDJuoUyYhUyNpQgq/XWKx23epQiOgnJm +rb3AB8X3TE40LneNfKdS+BNq4q2s/GYrI0BfmZ1BXjH0YgR0iLv1PZl+0L7++RHO +wE6kjuIs64UCkzIzaNByVUuAVRRqZUV0j6U07ONovqhPSNwky4h8VBaTLHWOfK4Q +k0H8p9E549WS07pfmKIgoKvh +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/002-client.cert.pem b/fabric/etc/ca/intermediate/certs/002-client.cert.pem new file mode 100644 index 000000000..34a874604 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/002-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA4wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkwM1oX +DTI4MDgxMDE5MjkwM1owczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDGfv6XkzO866Bi+rVZNGHtOjxXZE0HW5rwaxVQ +3zMtk/8Elrlyr6ZuguObyUfLJdnScvirjaGbUqm6XTL7H9yRUKBshQZDtaci6XRm +4gq21X7pQ0f1oUmsW5q+dDqbJ8JJ+HbEhbPH7MmZfsTLIASWMKK/pEzTf9t98fyN +4LJO/Yr++PmE7ZEz+YRwGphSupWEatLlfRh7XviihxKcXTiH8Z/qD8A6W8lngu2d +HFU7VXiBITPwvx/GeanahwduqpnZJNWaCAA7h0MCCatJ01ITGGPgsBCfJWyezBw8 +CAyLWYL/dlauaq1q5Xg/Bp8V6HddEy20QypRxdY/kPobAcVPAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAAA9Str4WlbxQaKuzZ38glD9jjkCE +tA9jwCJnNv5uh1o4z4RFLPK4s9EsY28g13LRKTm5ft0ndO4ofTb0xUDH9ddeTjsY +QtXrzrh79MzH9IIIyej8YubRqeVeQdR0a0RoG4IACziaA3hrZlIDbM7xxrXKYVzC +dvV7epVT1bO4TrIf96/JwHBBtbWBi+GedOtPgAxlFQ99nvlPEeKIEmp9kv111Ot/ +WpawpVE6EALDFAS7rT3zU2t/9qHtWb6i6QMGdJ/WKsHVOOMRMhR86tYKxYz1M4Ux +NI/2GQCdYSmbmzAdKKWWrrTCMal6MjhPjWnFyjXUgUkSuIyfJ8U5MQ/0hI8BF3K5 +SqH96WVoKGud0ohPC2bjdZ8XqRHvBU6nhJ5pnNA8YjMevombwMWOAVpYjfnCJK39 +hODeOiwdDm0AWDJ18wcAnyJH+aX6L50y2BWhE2Gc90P2kqA6YgRCAy2rwBRvDNua +yPGSyHJfNbyQ8e6tVbWDEkIQkP1A0uDD3SxoWNcxOeAmtQV6Ig779pxZ+GqHKR57 +bJ5wJjFJsPRgHz/ViP11IMffldb+6tvMKR4iVZO2eZ9GPqIwxXF154pKR2lL+mvV +3I9kBfkYLd4Z61hTmCAJpZaIlVTGsjLAU2W56m/OOI8piaZ/UUMMrFiVtKuFp6kF +OcrllxHkVaVgFbA= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/002-server.cert.pem b/fabric/etc/ca/intermediate/certs/002-server.cert.pem new file mode 100644 index 000000000..3d5835602 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/002-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAowDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjczNloX +DTI4MDgxMDE5MjczNlowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDItc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxn7+l5MzvOugYvq1WTRh7To8V2RN +B1ua8GsVUN8zLZP/BJa5cq+mboLjm8lHyyXZ0nL4q42hm1Kpul0y+x/ckVCgbIUG +Q7WnIul0ZuIKttV+6UNH9aFJrFuavnQ6myfCSfh2xIWzx+zJmX7EyyAEljCiv6RM +03/bffH8jeCyTv2K/vj5hO2RM/mEcBqYUrqVhGrS5X0Ye174oocSnF04h/Gf6g/A +OlvJZ4LtnRxVO1V4gSEz8L8fxnmp2ocHbqqZ2STVmggAO4dDAgmrSdNSExhj4LAQ +nyVsnswcPAgMi1mC/3ZWrmqtauV4PwafFeh3XRMttEMqUcXWP5D6GwHFTwIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAKoioClffib8U2RlOXTD +oPc5FWW6pPQoYP8Acy67G96Pacudy7wLWO7TI1s5KQyceyz5ZNmITtfXMgxJbCJv +Gd36fikb2iqlfMM89JWz17M5wTpZ83DRNLqDEL5NkEy6DZmnMd/w/saRvc2ZYsul +CaNsK9xQBgwesYMC80stTzpiw8p1sDh/JDjMDq+NodNtxgFN4nm7wIbmRRS2V1si +jfSAPK3cMyMNEGp/2C5ELpEq2kbHX/J4GOlva5c2g6Jte6sz328pCSmklNnGpjZL +HsSvXp4YUFwlcsF68qg9z/XRMvjodxQL5Jgz7Wz07lSIkqmRjZbECXXmdkyml3+E +zB2xIEzTbSG38tKOZ9bJ0KN7wPVUgZzIxX96/12a2q+fVVtKkVVQ/Yd/M9CpP8Yh +PRAznJppvYxdVpGIFyyD28b1K9TH3Hgo6W5GzJCqDf2tr+xVsLyoFu+ctBj9OKoT +yVW99v23d8iNiB4Kj4CIXIu7gbp4iJ1FbjBzubDVQnjwTkv3KnW6oOXSPN6rAg3+ +Pa/fizIAw5ScWg8IV3jrVrQm5XOr6GN5dh42f9Pd5BSjKO6uL5asKPD6hptAKdYz +DTs13LHwtimowZuhZ0+fmthHMLTCygkXUwLmDEka6Mqivhr4zdBjVY1qQefOjm2W +i8pWD20RqNu3F2f0HL6JZQ1/ +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/003-client.cert.pem b/fabric/etc/ca/intermediate/certs/003-client.cert.pem new file mode 100644 index 000000000..e3c7588b7 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/003-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA8wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkxM1oX +DTI4MDgxMDE5MjkxM1owczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCcg8MIdQyQgc/av7DR8Ulx8ysYWGrT8wIoV515 +O2Vn5V3PGNJqosNzOyVmPRhRxN1Bmutj39CA53Jnjb1BgH4e5WEdqWoW2pfuf2fk +kx0zgoxRbiOFT1+SmcUKQo9m6PfsAGuLUuW2cvPLNk6SPHuGbcvPkP8jUqjsP9ut +ewVGTiJto18SbOANg7PuVA76feeYPOitaDaX8kAGTsaNMEz/lriPCwzqrwpCfw+I +5QW91u/T52o/O4REKCno1/I3FJpk3LbEAYiGUtXOVlv7/HBj4BfCCpdcIA9P7TYk +v1dtadylT4G1lnXz+OoOUFvvIoFBaNB/x4zDVvIpncpuz/CJAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAqfnYmdpLwOKsqoh8EXMdsa9AQeRy +MiqZEpyA6tCkfthC1qzFDr4L5Gb5eXZI0Xo0yYMTvMx2oaP/zu81EEvsj6L5Tnig +eaZqqm7DlUp42FQOdikv2OTctuZ2y1QAsE4+zStawE7il4ED5C2cTDbVBZccJa2X +jl7WB4505Ucec+fmgX7lQB99/NF5Ca9cCnvhb71waTPsV9GTXTBYPvd44N2g/o7y +Wq/3ldqMkdj2TrPTWjVxXfDD6CtHCAyXpJmab6tHSbiquYyHxBVgcJgxrlxxpH4U +/xdYPjRHqXh02q42Pm0MwIp05NdcxcUv+H+9YKlqr9Mz7zZdbjb22QbfZr+59xwd +V4QW+EhEV0OWcAvkbULosSolm6EZX3QmfET53rZqlXf2FSTSF+J6DhQ0hCIIk86D +5Sd+gHO2xPieFtFD4DdcW/RLa7a5csIFg919zpADT3XOc9bM27gcBc1uc5h9Ov+/ +KzGRcnobI4f5sRgAJumLMgVF1iIE94QJpC07zmzy6t9GEJ3z2t24v58Ai6h4THg0 +CTa7FCZzcvNX7dTu3tueS23NJtQNMq89sOJiyrXFi/8+sgnqz+ed3QMtPpU6j6bf +WSXtC7GDkumLYMxnQm7v9eVjO4EkC+2dOfIZBDI+nrGXXw0OpDptXgGQEmFC3ie4 +2M821rvVbFSjhDU= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/003-server.cert.pem b/fabric/etc/ca/intermediate/certs/003-server.cert.pem new file mode 100644 index 000000000..6b3a7b081 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/003-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAswDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5Mjc0OVoX +DTI4MDgxMDE5Mjc0OVowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDMtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnIPDCHUMkIHP2r+w0fFJcfMrGFhq +0/MCKFedeTtlZ+VdzxjSaqLDczslZj0YUcTdQZrrY9/QgOdyZ429QYB+HuVhHalq +FtqX7n9n5JMdM4KMUW4jhU9fkpnFCkKPZuj37ABri1LltnLzyzZOkjx7hm3Lz5D/ +I1Ko7D/brXsFRk4ibaNfEmzgDYOz7lQO+n3nmDzorWg2l/JABk7GjTBM/5a4jwsM +6q8KQn8PiOUFvdbv0+dqPzuERCgp6NfyNxSaZNy2xAGIhlLVzlZb+/xwY+AXwgqX +XCAPT+02JL9XbWncpU+BtZZ18/jqDlBb7yKBQWjQf8eMw1byKZ3Kbs/wiQIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAHyJ6NQTPGg/CJTC/9nb +KHaMra0aFLnvNUFXCiRsLXY7VNx7Z8HsWkm6TrTsTPIu3deMxfg4Rvxc0vDDsl2p +YU3rjUNMpzWZQXj2mNO1cPdG30fAIWNCc5qiGXoI2eJjEDM5QXyLMVqneTg7PQ0g +cAnf6h6FLmifhdR5e/VZPEG9mEhubETevmIq4lSqQ1lopMjihT1fC9l+a/WaQXxa +Ic6Uq9vHdGONFgvjsnjXN8py/zKw303mnAXOEHiaznyxJ2+5UjZ7IYxcO5p6soJR +XkkHIv/WyAM+kfljvzVjxx2jTwV15L+399T0x8g5F0fjwd5c0H05JcOfpVB1gPq6 +HZ+B1wyRs5xNQtYJ9On8KIW1Y21fzjUhKglhGrZ3148DB9WJ/Fk7CJUEuTk37E1L +LIhI4/ml1fvE2VNmPabI7xjMtFRaALRKmAhGINnI/guAKHYJqcSQIBIJfOTrXYx1 +Z2SrT0sUre2toVBNzyyI68m7eGOYaMCTOUL5gCI/SXf3r4LKhNitVow8Rw3Xt1il +9xRxZ6SzTs065kjJys4Tuw4a+NF21PVq4dD/HVVabQRDf/6OubjAARo4FyomWsyy +nkWwIoZi21e2F+RM5rnuXUuZ7/eV6dJPfBQ2E4y4E0qE+vfNZpMi6OnJ1xdTfTx+ +z9e60k+pZ+r/ozXQ2srE4ZvZ +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/004-client.cert.pem b/fabric/etc/ca/intermediate/certs/004-client.cert.pem new file mode 100644 index 000000000..1ee1af0bc --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/004-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEBAwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkyNFoX +DTI4MDgxMDE5MjkyNFowczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDQwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqBDdOcSnf0fCctQwn+yyjygU3qqx74bQEpNh0 +YEstPxbqOrGzkUUV6vIqMAfyQDcEAaXbxh35/W4ms73waN/+swYDkQVbUn31qB7n +psm/wqTz6NVUJ0r20KFJMVoGtfqO991gl1r/xFT6gc7+v+hGj+6iAuMED7v3xFA7 +qNRD8N+iNzq2ArdUX4OfMN0d2y1Zq5sBqicA3vMV91+KDvKfmQRfGFkvyW6Y1S30 +WDEWHVCgvmnnw9l8+A8kdEe5/YQbBe5bwdaLYCtv8h6Jz16Ok7jBbrrasYbpcsD8 +wOI5CnyuV7wKcSFO/vcEO/P3YYqL65puKGKVMteyige4/rpvAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAe6zSSoa8HWmjvtV6+aktA9vUgrHz +uUtw3OFM/4Gg2U/M1pDirBobh/EZwDqeTNqVFLBibMAWj3V0mND+SLm0V36hOFiE +lcnYSJXYoErJ7LLScUfRjPZdu9JhNl8DoQ8NgbHewVZhecA1MbUsTCbSNsufREM8 +JYbd9+C52N4hqdfxuT+8imGE1Tg3/9CcldukVC4XNBhSYskhy7zMf6UNvTpBH3EO +434fraxCjgnPiQJq5S6Bq3Oq1Kbr0o/l7gLNIzz/KlOBJQsVIPExFEMQ7kZQzDQh +AmvuoRJEWB3fdYYmxGPOB/pJH8OIjyzcyC3XNDtyz51alXD3G40GHECO0Gnb/Tvo +kKODky2nPWrlVuoY6R6bQsFojsUQJSifz3p6jUE2Cpv3/axg0juumJKaaDJqoxVN +Bp1vGS+IIcj6nZEyfuUCRkaBAssUKXC2i1uTeoyovsBkjOef9fyclN5ym9/fsyUV +AnWxwpxIrfG26AeV2nenRLFUqzvP5xJNF1HBwijmOdYn2tlBImxv8ziRe7JhUyxE +fXiqFyEgaPDJ3SgDEIzmYd1tt7vqzpqJHQOe4hJDoga5q+qX8IJOJEz2vy6E9sm9 +tGdVTvJG0422Hlk6OZcitD+zavn8KjVQ8mMszbm3LurjBYO3830KhAWrOiN6f8gg +X6sIXw8/4UKo5d0= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/004-server.cert.pem b/fabric/etc/ca/intermediate/certs/004-server.cert.pem new file mode 100644 index 000000000..c2b965de9 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/004-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAwwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjgwNFoX +DTI4MDgxMDE5MjgwNFowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDQtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqgQ3TnEp39HwnLUMJ/sso8oFN6qs +e+G0BKTYdGBLLT8W6jqxs5FFFeryKjAH8kA3BAGl28Yd+f1uJrO98Gjf/rMGA5EF +W1J99age56bJv8Kk8+jVVCdK9tChSTFaBrX6jvfdYJda/8RU+oHO/r/oRo/uogLj +BA+798RQO6jUQ/Dfojc6tgK3VF+DnzDdHdstWaubAaonAN7zFfdfig7yn5kEXxhZ +L8lumNUt9FgxFh1QoL5p58PZfPgPJHRHuf2EGwXuW8HWi2Arb/Ieic9ejpO4wW66 +2rGG6XLA/MDiOQp8rle8CnEhTv73BDvz92GKi+uabihilTLXsooHuP66bwIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAEPPwvTShn9x9E0um/Rj +HNjGzcuShd0E/tWlUHnn9F1i6Bz0SlbYngbxIiQUxgmraRtzH5wH4Z01xE6vdA6S +unckj1XyhwGTV+pufxSkRk6Ox67MZjjXOst36hyQjWNsNf3xDaPFxAvxqWqaMJdf +mHAUlDiXIw7kbuZM/eBGx97wNf2F1YPSnvcfPir5ZhGKg4K7ZIlV0Opvemwgqf0s +vjkQPRpnILfrInQbOlnFEDMh/tMN6eIEGPDX1MjmMS9cckr5ZacevrjlsNyuM7C/ +QrVuYHFJ9Le1Eum6GjzMGILUxADoc3r1UgDfaysIaru02lefnhfNeOYixjvV3Dkc +rGH3Vtwc4a8M85qh7oKlJ4+f1e3Qn01LmDlD8Y99a30ebbtfApCCUbHJerXoG9Cy +J7hcFyO6ZBcTHfVWsHjAoL2oojdo6smbf+7pR8+pxAdnExRsI3sioaw9nnKPCOz2 +T6NzlbvCts3d2Tpi9eJg2t+uxA02e+qxC+MIk+/xlZ41VvIkUsB4wQzK5nBpziCs +wGCzR/C0uHFUVPubQd0oB5Hh09Z4Dbff28m1N/Aqkty8SQGwz9sJAWVDN60cBGIj +f+NhitZf6ERhoZUDODuhcuNmCilmZn9inPIGgtMVhtWpFXIB3eSoMSHKUWyFeOfj +mv9NYvwrZkt0PCGOxCtwXAYV +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem b/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem new file mode 100644 index 000000000..ee6e52da1 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem @@ -0,0 +1,70 @@ +-----BEGIN CERTIFICATE----- +MIIGBjCCA+6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw +EQYDVQQKDApOZXRGb3VuZHJ5MSkwJwYDVQQLDCBOZXRGb3VuZHJ5IENlcnRpZmlj +YXRlIEF1dGhvcml0eTEbMBkGA1UEAwwSTmV0Rm91bmRyeSBSb290IENBMB4XDTE4 +MDUxODE2NTcyM1oXDTI4MDUxNTE2NTcyM1owgYsxCzAJBgNVBAYTAlVTMRcwFQYD +VQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UE +CwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNVBAMMGk5l +dEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAsb1EPhMUweS9WpjT7L54xAOmZqugJ6fhSrFfLUwNUy172q+ASvZT +pT1zKIPcZpGmPB3TX2bHaAR67BbRkUR11JgWE3U8+FsGrYmPZtaKM6fg8Mh0WZ41 +oMYQNJyQixOktrgqfybyJoT5PeT5AA7QQmd8mku2X9nkAu6gWPf2nHNc7SeQdijm +yQQaVK3oqyaxOzWzsU/XbfMEz/ObkefUxgt5Z6jlK0xcW0Q+QgtawMKLUiuo6obW +RPcl7Hm9Sze8XJS5pbvS5JkUszxoRZuDVHZylrlHIpA/IL+BnvS+M7SP28UWe9sk +rv/s6ACpJtuPJ1EYf5fakugOpY7i+hq7YNi//csbc49Qjn2OtttrR7JcTaHUEU1I +/tQbQGAtNkI4pJjRVUdDawQFQlWHZD1COixNLErs2HzAI00DhLrY6SKITI/kjN0X +x010XdMcdfay0PLWm6RwxiRmMQFL4GNIC895NF1q6xV4W4rWgqUNlcvKpy+i1chW +pRbUHe16ul0qh10fcESrRvAbXn5YrQJLrwbSr+85ubN8lYdNLE0qg2cIXZlUilar +ZZzWghtCe+KkUpjfRuAi/CqfSwNK3QXEfeVEK6S49mHeSekOizFIw7fmDhCz9vXw +MOnbryRSLEJks0gIRcSDVChXheAqC98y4kcQdniNWFnqJXoqA+rrSokCAwEAAaNm +MGQwHQYDVR0OBBYEFK8UXC/sq6dGVFAqEXHsQDzqzwuUMB8GA1UdIwQYMBaAFEHz +6RRuOuXj2mwAzOeUinfWeivpMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBDAAaOE2Nbb49eOjyTNxIeOB+ZKQjJ +1hUEgRrootAA8NYbtKW/vyxTWnNi5XOGXd4DFS9OKZ0mL/7NyLc0mbTwPH2ZT8KT +PUTSCpo6yktZ/7TMjyAtWZiOMg2EH+6m/nlNSXk/v5fb8+JQLdZfpxoA017dHh3t +c8l7KOskCZNwQHgF/YMXrPXUNbsGkXRuJLtpjPw5O9GvPys7p+a1aJH1WCTly9zf +B6j+rMF+UGCPDT30sxitVlohik83j6pKLgEAP/gi8nJbILlTP7ce+gJeHR2tfDvm +K91X6QgCF2STUFBU7/9H1/pPRRykOxQpAd8xqSgqGEyp9Ie4tysZjwoUEnG8IVJ5 +ykrIFximvnb4B+LABV9WEo08n8m1R8wEryrISi8fBPn3Pr5nuayOfFLa15CLTkZF +40FN8ika1qNZy8bWRDwTZJQUUb7VCheRWcMwdZdNmhl3J+VZLpQ+ruW7b2ajwacH +z5NwBHKNcmxXb/4vHq/BnlcayHnSqT6036+OZQ+owDegcYmWV6LaM7xLErjHz2EE +38M2YSiW5SU1zluDe+iHb6l3Gd3Fj/X1gkMWFgYh0XPMSUSyimLNYzy4THKzmWlc +QNFoLLiIDbLrMt+vk+vBkIsNTTPXRJOFPBhmIF6uIUj+2YhzNotX/pQtqMKms3pP +lmHqdH6biwygEQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGFjCCA/6gAwIBAgIJAOq4qnKYsnlbMA0GCSqGSIb3DQEBCwUAMIGXMQswCQYD +VQQGEwJVUzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExEjAQBgNVBAcMCUNoYXJs +b3R0ZTETMBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UECwwgTmV0Rm91bmRyeSBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMEk5ldEZvdW5kcnkgUm9vdCBD +QTAeFw0xODA1MTgxNjU0NDdaFw0zODA1MTMxNjU0NDdaMIGXMQswCQYDVQQGEwJV +UzEXMBUGA1UECAwOTm9ydGggQ2Fyb2xpbmExEjAQBgNVBAcMCUNoYXJsb3R0ZTET +MBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMEk5ldEZvdW5kcnkgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMqr9dr7vj0KvdYkZgMMgS00ohGd +MVzpN6JFKb87uEbb7U2uH905uNkm4OOyilY/w0UD8PCU3ISmFgoB5LAcOa77icV3 +qJ+h4MTaVirps2EtyA34DcyU3k+Fvauc7fZhhnAdcZai/6O13aBorR9awfwJDGfq +fa/uq88xN5gU/yniOpNnDZu9lbD4sxhMULLnjUMWpAtBqwyDXSZdEBVc7s5r3L4P +Wt7XMurjBLq7wi0mgrN+a9mQy8P3QL+1Di7SIlovsYHZIT0w48N4ZW+mehIAiRJW +a9ENQCPbH0+66TKTOgvU4BbNzkKD7kvFGYt6NUTs+89wdpO01qDa1EPDa9sx4Uo3 +w29AfVBhxo9Zl7hWX1voMC5NoflE33X0f8X5kfKNnJtU/ALXiV+Wd4grI3LwkRX9 +gwhsQANae6J53MN6GTY6mf7T71mvZf/F+MKjyJYcVs1pWdBfvB1Fo6jvzeUSi6dy +p7joUMEsGnIC4ModCkhPcwryuQL/XIE3Gwfji8zB5Rm4rS7s8L0oe2alB+5+VgZ/ +EDfiRjpZTePPJAd62gtiOjFOo0QSO4anDLajWPtFoIEQUhtiWeVuGkRYVNpB/3rP +YZDqbVTfLsnIN+UdK70WjUk2QbepeyMPB1r/pbs1ElGB0WuGc7CubsXov1fg/Uef +NT9UkvrovA+aIdWNAgMBAAGjYzBhMB0GA1UdDgQWBBRB8+kUbjrl49psAMznlIp3 +1nor6TAfBgNVHSMEGDAWgBRB8+kUbjrl49psAMznlIp31nor6TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAJ9TvhopZ +E5rGe57y1lvk8WQRucNFxGspdGGem0DS+uAHjJ2djFf2EQFkPyjo8HLet7C+XmZ5 +I4ETrPJvgkPzSUd3MdJUUjBvOw054SMKyW/88D/dj4nsMK3qA80wN5i4Syx2p5KI +yhjPaCe96fh+VIwqBMAl3f9KlWuffkfNeJT0ySYVWk8QydNy06PD4mdwKQbn4P03 +Xh3G2Bn+1R9sf4ZR+HIZXFF0+tfkpCoDJqkx8Roxddrwo2zs8b6wOJJYj5KD2NQa +3GCR8p1U20Vb5AxfLLt5PeJc8D7WvaEUCGB8hoa0ElSHE8cyEq2NsCABf7r7YPcY +BtoPX6VxAeEqvLeHKBDc5fv0UlbrPI9LS2JX8t+i8epf/fH2rk9NUE7AQ5Lb8sJz +hHYztL4cg9/h5In6cfi4Ih0njZYKuiv+ZGy4vuB4KSyLvQYe4LKc/jKpAWzO79S1 +sESw3yWhOcuk4ifFoYHVjxQ+bXhvYujX/ceSgxWHT9RocnROadnWvuZ8aF9HIBlh +F29PWwH4RvhvkDbMRmqxNz0jAU6GcjhmKU+hnmzbF6OqtXDcZK+i8SF2mutCa/G6 +H5VDbfL/7/jP1vbFbIO7bNW94HjCGo97auSDEmsSXgZ8uTYNb503qPzdmXiU+hRl +jDOQLqtoJofIWUChpNurPQfqu9UljEk9LpQ= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem b/fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem new file mode 100644 index 000000000..e307d47f1 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvzCCAqegAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDMwN1oX +DTI4MDUxNTE3MDMwN1owezELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRQwEgYDVQQDDAtjdHJsX2NsaWVudDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGXmeb1l8EjH6EbDgY8UU66MFB4 +2THjA6DwHRaU8TVaGUqM0HUwA6o1oOuDDaq0WGExVTW80UnQC9PoGKO630JXAIh1 +ouLIGLCTRwzuHeDdFqh94w/U8bpt8UmdCwM4B9SAbZNWJtzQlR1bH/7NdujyQHhr +064hESpQeXERt5JD9kEnTaDTBmRBS2Va/piq+O7os8Xdxwm//5CgFJ4mY+Jx2M97 +brH5vo9gWI2lWHo3MrZS2CryNnYv3KETwpsz7FnSab67sch1yg0Y1ewpjXpytNNv +PjDN9FmP2DPcV2pecZur13y5urhv73sOYrFIZeO0c2ZwpPYQ5H11jpEYv0sCAwEA +AaM8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9jYWxo +b3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQCOuukYQ6cgstNbbYVe +xJsKRRdLqIdkHthH4dCtOaB5MxIH+n8CpAWwZcepbf6/RsPnsE54kVw1rJwgbWxY +Leyl5iVyuSzQ2NtiJOJAqHiKWLi965bs8e7rHEK/k6AnRpCaqXWZKUMSgFJ1wyLn +B602AE9OHkXgXumNyjE1IVP30BKd4DYOtB33Z3J77F3UIcaDcaU6IJThVO4VmLle +Fv4Vnw8iMvMfAy0FuwAahHEshFW53HW5ZSoi4a8BcwRNy17xQpGKjAOw4naOWe+H +A1T2ayKAGMA9jFcXKn7+lfTSgYdwmhKUGMQTlsqdpHktvBjQUFyPcvMt99AI5Amy +0MNaTQ/tXr6lb3ws40YFOqjD7VKhJcoqcwHqX0xXfI7X0zYNY3DGVTkvUnWTDcle +pF3O6ZKllbL6LKFkJXJRVhqOuomsAuho+vi2A3la/PBcF48z4M0aH8j6HGftzgNe +AS0Ys5iOqJhr1qdBils6hSL84cCsNYyHG+V95jdwNepSOOBqc5+OydFoUjFQScK3 +Q3bjV7T59N11yCMOJzukrJorGtUr/nRdQPcEsCQlvGj60+kx3FEygBIpeiZy5AAS +h7KoWY1Sh2l4YW0Oh4AmeLDY0ryBXDafgAuwGFh7zENLBjDitdpFSuo+d/YksOnG +CR1KiiHDLLh/aqOiR7T0/HKFqg== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem b/fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem new file mode 100644 index 000000000..c2e4f6059 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuDCCAqCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDE1MFoX +DTI4MDUxNTE3MDE1MFowdDELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQ0wCwYDVQQDDARjdHJsMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsZeZ5vWXwSMfoRsOBjxRTrowUHjZMeMDoPAd +FpTxNVoZSozQdTADqjWg64MNqrRYYTFVNbzRSdAL0+gYo7rfQlcAiHWi4sgYsJNH +DO4d4N0WqH3jD9Txum3xSZ0LAzgH1IBtk1Ym3NCVHVsf/s126PJAeGvTriERKlB5 +cRG3kkP2QSdNoNMGZEFLZVr+mKr47uizxd3HCb//kKAUniZj4nHYz3tusfm+j2BY +jaVYejcytlLYKvI2di/coRPCmzPsWdJpvruxyHXKDRjV7CmNenK0028+MM30WY/Y +M9xXal5xm6vXfLm6uG/vew5isUhl47RzZnCk9hDkfXWOkRi/SwIDAQABozwwOjAJ +BgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SHBH8A +AAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAGH1o/uGn8QdwnM9LyoGfaDKCLYZ +p2w+9Bhpbm1RcOgg8Srw6yJHQHrDJgVAH6YYDaueS1TTiUNOUDmHLBuX4AGPga6h +8sxVsB0faYqM82yDXO/wQdw5FmcvBNFpchK5R72L7NSRshdq/VUL+FsWdQw58uLn +s6QDfMme3fU0WRQ5vAkSEm057BKeBXviRT9xNcnYMTlqZaQE2pEdzPG8xicBJNvL +V5zP4HOi63/it2Tv1M2YXVcriBXJkx023CHKZ4tm2enqVofZLyjvzqLTeNuJc0jV +zwjBpp4hG/dNc4p9kl1fQOcd7N6EfBggQy3f89J2W5X4AXBgCjxcubj3pg2q2qV6 +83d45xD4K1HJFRlgpxg26Z/e09GL4yUdST77elv+SKaYNSOuyzOu+IoBv8GHEnH4 +QqbW8/56taQ9bUSGw+r8yvv7uw69bPig1OnAc9hZ4cc4yOVnzW7L98OeKae/XR5I +Ewv1kvrv7ISsYKjSOIGtcQLZ2/xoHsf3xJrZ14viG2OCoRj93P18xod2yi2Vgr2Y +uBdknNjcV3SVv4dsbU8bMSHTThlQM5qrPZHlnbQjncWwXesLCUqeL0O7Tzz6lGT6 +rpD1hgO9R3c9Vmqa5g+Anqbv50YTt+57M5NcLtHTAdfWIOa92LZF8FOpqTE405A/ +xLJv+nDUo0iraA3w +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/dotzeet-client.cert.pem b/fabric/etc/ca/intermediate/certs/dotzeet-client.cert.pem new file mode 100644 index 000000000..a6a2f8ca1 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/dotzeet-client.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCAqOgAwIBAgICEBEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5NDQ0MFoX +DTI4MDgxMDE5NDQ0MFowdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdkb3R6ZWV0MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtMRtlGukei2+nYGjLbgvSn2JNZO7HGm2 +Tbh4/VfZ9GJquE4iyGoRenNgyEP1LdoBkYlFGrerxO9cOR4o2iPNg1IhnOp96SxP +IE5ogg7pfU9waewlOhULjBwdPDa/cmBIwV80eDX6X7jAsSWtCxnaB7QwTJNRzM0I +9456QKEpzrOHv9kEUzeaulD/T5eFGRAUEES1h1JdVp+Ay6ZzbE4n208VdNEDV1bm +61VQ5RSbzCRTvoIE2xBwt8YtBlulz4aof/Wm0dR5zzcQqXeNrU4W3jwpzycSEyop +5nBoYrWmjg6r8oZ7PVPTMD+AsBFfzCecrTGCOSdHNWf+p5F1KLvZiwIDAQABozww +OjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SH +BH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAKAGn986vhFHlxQ1bG0+hQdu +vrSG7E45Y81AuospC7ABm74Zny/zg3choeVTcoZoKmZhKAPizX5LMbkML6x/kjQt +jbZFeez6Q1LAn5IdiDlLUXY46/HubClF/gfAaJcQP9h2CQfqhqsl5eVqfbcz3fSB +MMZYuAs6DcaJcS2u6rIXmH89F69bs83o0kdiMTFyC35WXzh1d0lqbi0p29Bc5Btd +eEgbHEqyP2oYASCI7hSeMhIu0kRhUsGDvBER6Sag6k/L7t6lrQ/r1EP2ss0ycheV +ShdCaX3oikH9LFk9hSBTGf0HGxwku54GFRU3ch+EeRHd6iJj6cVKuPV7cpmNFSF+ +n34byUC01fbjLhlszJIGIt01R+9CercU8MyoD7+TmzY90yu1PFZ7B9jDqkkUqSyQ +HPE/diq0Is/RoI0q5HL6bqk+/HwQQ9XcvCsC2kbijtGVMMhBRl7m2GMyiFtWlhVu +trNWaOj9tXlbBIkERgDWRteCkMgU6zjbKvqepQC5WAkvu0LnhpbhTXqjaNGZqBio +1j/BKp+6ozb1Jamv4C0/rmEMBRH5Z+X9vqDmkAwLJb7wZySrFBQchvKnPnwHUQv0 +JniImSdIKbiAakU4v6wMCft6tDvDmWKuluN3JmAVz00y9/vbVwMFdrRQQjlePDBR +XG4LbZTH8lXKIrLKDCEW +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/dotzeet-server.cert.pem b/fabric/etc/ca/intermediate/certs/dotzeet-server.cert.pem new file mode 100644 index 000000000..ae28a9b83 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/dotzeet-server.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwjCCAqqgAwIBAgICEBIwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5NDUwMVoX +DTI4MDgxMDE5NDUwMVowfjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRcwFQYDVQQDDA5kb3R6ZWV0LXNlcnZlcjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTEbZRrpHotvp2Boy24L0p9 +iTWTuxxptk24eP1X2fRiarhOIshqEXpzYMhD9S3aAZGJRRq3q8TvXDkeKNojzYNS +IZzqfeksTyBOaIIO6X1PcGnsJToVC4wcHTw2v3JgSMFfNHg1+l+4wLElrQsZ2ge0 +MEyTUczNCPeOekChKc6zh7/ZBFM3mrpQ/0+XhRkQFBBEtYdSXVafgMumc2xOJ9tP +FXTRA1dW5utVUOUUm8wkU76CBNsQcLfGLQZbpc+GqH/1ptHUec83EKl3ja1OFt48 +Kc8nEhMqKeZwaGK1po4Oq/KGez1T0zA/gLARX8wnnK0xgjknRzVn/qeRdSi72YsC +AwEAAaM8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9j +YWxob3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQCD/bQOYXMhywqT +UsWgLvNsff5R3xT2ddn/ECN0KJSGZKYnPrCimWAVIEz97gVgPQneLyYz2aAEbARR +IFvnKt4saXb/jbTNThV43IU4kTlpU7B4VY0w6RjmMCwpCwokIeRLNIU2SmswApoW +isVBIeZ4LTdByKy3a74rPk8Nbt8pOa27adWoLrO9bxjReZ/RqeWwSVVOgVyiVkTe +UadIADo1HJoFouyvjJsNG8E9B2V5KZ9FgdbJzGKKlMkHd1DoauNHTcORwcLz8G2X +rf9yEiFYQKlgYaHpR7YtblVR9DiWtT4Nd25JeCiTZ+1/npj2stt+ZnjaZcFkLh43 +1Lw+HlD4eR4MLPEvlcBvmpTJcTOCY0ZL1GLK+Ip1dL90cseIBmON07zIqCNKLqUF +baovuK1MTG/Hs/y5N1KOBFcc18O4F2DpSW0hD7AEFjEArs4mUwGrlqroCNjGo4K/ +CAXVltyFQqxWcPBzNYG/HKgYe6uatAjPirQrV5p/8CXOzXP7nEFF5t1tppilseib +Amb8ClAby+//S6bDsvcaRNTtYVUJpv04ScjiT9/s1nBleGx5RMsz062JUbL70S9j +bjBYvseajIZzaMIUL0zc3wNFOxUVCTaDMxt5GxO24YI8JBrRjPbpzLesJ5iMmjZq +3hgAjgNwSNau0M0jKoqYSoJgBGnZaA== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/intermediate.cert.pem b/fabric/etc/ca/intermediate/certs/intermediate.cert.pem new file mode 100644 index 000000000..635c498e9 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/intermediate.cert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGBjCCA+6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw +EQYDVQQKDApOZXRGb3VuZHJ5MSkwJwYDVQQLDCBOZXRGb3VuZHJ5IENlcnRpZmlj +YXRlIEF1dGhvcml0eTEbMBkGA1UEAwwSTmV0Rm91bmRyeSBSb290IENBMB4XDTE4 +MDUxODE2NTcyM1oXDTI4MDUxNTE2NTcyM1owgYsxCzAJBgNVBAYTAlVTMRcwFQYD +VQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UE +CwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNVBAMMGk5l +dEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAsb1EPhMUweS9WpjT7L54xAOmZqugJ6fhSrFfLUwNUy172q+ASvZT +pT1zKIPcZpGmPB3TX2bHaAR67BbRkUR11JgWE3U8+FsGrYmPZtaKM6fg8Mh0WZ41 +oMYQNJyQixOktrgqfybyJoT5PeT5AA7QQmd8mku2X9nkAu6gWPf2nHNc7SeQdijm +yQQaVK3oqyaxOzWzsU/XbfMEz/ObkefUxgt5Z6jlK0xcW0Q+QgtawMKLUiuo6obW +RPcl7Hm9Sze8XJS5pbvS5JkUszxoRZuDVHZylrlHIpA/IL+BnvS+M7SP28UWe9sk +rv/s6ACpJtuPJ1EYf5fakugOpY7i+hq7YNi//csbc49Qjn2OtttrR7JcTaHUEU1I +/tQbQGAtNkI4pJjRVUdDawQFQlWHZD1COixNLErs2HzAI00DhLrY6SKITI/kjN0X +x010XdMcdfay0PLWm6RwxiRmMQFL4GNIC895NF1q6xV4W4rWgqUNlcvKpy+i1chW +pRbUHe16ul0qh10fcESrRvAbXn5YrQJLrwbSr+85ubN8lYdNLE0qg2cIXZlUilar +ZZzWghtCe+KkUpjfRuAi/CqfSwNK3QXEfeVEK6S49mHeSekOizFIw7fmDhCz9vXw +MOnbryRSLEJks0gIRcSDVChXheAqC98y4kcQdniNWFnqJXoqA+rrSokCAwEAAaNm +MGQwHQYDVR0OBBYEFK8UXC/sq6dGVFAqEXHsQDzqzwuUMB8GA1UdIwQYMBaAFEHz +6RRuOuXj2mwAzOeUinfWeivpMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBDAAaOE2Nbb49eOjyTNxIeOB+ZKQjJ +1hUEgRrootAA8NYbtKW/vyxTWnNi5XOGXd4DFS9OKZ0mL/7NyLc0mbTwPH2ZT8KT +PUTSCpo6yktZ/7TMjyAtWZiOMg2EH+6m/nlNSXk/v5fb8+JQLdZfpxoA017dHh3t +c8l7KOskCZNwQHgF/YMXrPXUNbsGkXRuJLtpjPw5O9GvPys7p+a1aJH1WCTly9zf +B6j+rMF+UGCPDT30sxitVlohik83j6pKLgEAP/gi8nJbILlTP7ce+gJeHR2tfDvm +K91X6QgCF2STUFBU7/9H1/pPRRykOxQpAd8xqSgqGEyp9Ie4tysZjwoUEnG8IVJ5 +ykrIFximvnb4B+LABV9WEo08n8m1R8wEryrISi8fBPn3Pr5nuayOfFLa15CLTkZF +40FN8ika1qNZy8bWRDwTZJQUUb7VCheRWcMwdZdNmhl3J+VZLpQ+ruW7b2ajwacH +z5NwBHKNcmxXb/4vHq/BnlcayHnSqT6036+OZQ+owDegcYmWV6LaM7xLErjHz2EE +38M2YSiW5SU1zluDe+iHb6l3Gd3Fj/X1gkMWFgYh0XPMSUSyimLNYzy4THKzmWlc +QNFoLLiIDbLrMt+vk+vBkIsNTTPXRJOFPBhmIF6uIUj+2YhzNotX/pQtqMKms3pP +lmHqdH6biwygEQ== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem b/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem new file mode 100644 index 000000000..9c0949e34 --- /dev/null +++ b/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCAqOgAwIBAgICEAYwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDYxOTE5MjQ0OFoX +DTI4MDYxNjE5MjQ0OFowdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdtZ210LWd3MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJU/MT5Om7hLHOj+u8f+rBlzdx6xcQc3 +99Fd6kLywH5m+jPc6VWrM0r6B+rrTMvxud1XvrwFQ5RZrYXvGkMqWTWX5ZVQeXOe ++UcBVhFKRx7F7V2mRLQiwgCswzWBsN00pq6Wee104GX54mj9nrovb/V4kX1q1NJr +R0rbEwIG8gceJGT5xt1bHsMpd2QXDqZG6s4oX4ib0QItxs2wNY+7YUuA996Je+6u +ihD/es2m4wkpjKb/snMEE1gResXAzGfLjBAxoCO7UlSC6wlrxnRsvTMYLWV9LuLL +c5PmzF9crMIU5LSKYIu6uNeWeuetco7QfZmyxsq74UNBlr5Z5tRRGQIDAQABozww +OjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SH +BH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAJTgeIOI7gCNOerPRCbTgHax +vajpPc12QIboMnbDEpo2WgLCju/P9DOTnIusARb1SuUG4FkI7x0AaSM23QSCWIw8 +hHvJg97pXyHbdSBr+9oR2eQ3/kzb0hMQTnsOub3O6Zqju+ZDyzx9OCygfXuacG42 +wj9GhdS1+NgXnImYqkdPl+OtWdrjNRL9VgGnrQSEVsJIRJaKG3AoQxBj7dO0Lwlz +gKkg6+o2iZETT/iEjdszYsHUjnUB5H/T553ruwRH27VV/4TppSGpy6GoOdr54oa3 +H8RDQfEzb2No6zGZ1voKmPp1csUqI0P8CH5T6sPGpmcokLCH53AjDsAAK8K2msa5 +ZQLoh0PunE4LbHdTVmcrHLl009uEoYzH4QCsSo0yA1qImtZah6Pu/NEAFZ2g8BTe +T2kZNm2laYL0kZXQs3uUf+T87uAFEBQ++dnCPVF6v0vAJy6eN4U8m87fncYK9XNq +/QCcqJCOZnEBJyBPaJEx7UuFqxPyXbU/rqk+VOlsaazhvinmgGQOQWFwej6ASf/Q +UTevZTrqVBCV+4YkMSGDCqczhYamsg5UpDqYzD1uHrmYDuHJ+MFGM3TuOMxtxtdr +E6KhXsMrfc0Gwg48x6l2KomhIWK/p0KZ49xlbUWXHurKZcBsZnxOelG4Q0LN4Pea +QXRit0jZCBdZCEReq1hu +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/crlnumber b/fabric/etc/ca/intermediate/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/fabric/etc/ca/intermediate/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/fabric/etc/ca/intermediate/csr/001-client.csr.pem b/fabric/etc/ca/intermediate/csr/001-client.csr.pem new file mode 100644 index 000000000..1c97e689d --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/001-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDAzCCAesCAQAwczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDEwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDbqcpLyr/yZFw2YxOy1RKhO/jw4ra8Z15KdEHNbz5h +cNlT6dmVFQj4sBW9AsB06ynqzrO5cKjnWF/LZXzTRGlDUmxmKZOZCcb4NVy/4fwW +NN8IBuJQBrrz1qTMBJaG4DRbZ+zTICrb2EJGJyNFZbNKvlRQzn4xMjMm57Upv2en +Imy8BHUWahjkcCG/uXPTJzjupTweRI34DPxTU2q3hH7zwocdFMe/mkzShMb1qwj3 +3BByHWzSK60NawE140li24v3ELLhre/C6cZSV1Nyk4U9jreSeaQ/uj5cmk08dPnC +eBcTqMIwhAOihMYM3vqhOZbNfssr7gXd0/8bv/7P6JGpAgMBAAGgSzBJBgkqhkiG +9w0BCQ4xPDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxv +Y2FsaG9zdIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAqNqHubzNgIzw +qCMV/Njoprd9Ia6JK8N1O9RnvhYJCIc1SETJCaNF4O83AmVCZ7HgDIOYeHcYbzyh +IVhfTlMdL1mkCq5h9f5TGokEBe+abMD2G9ff5l3MKMDi8SDMM7e+OyUignuCybo4 +rlKINukDR8Qn/UM4clBDYWp6VfWcnQNot1+1IJrMLigTmsn6Ggn+irNmFaLg5EFM +O6S6mObGR0CzEkPD/VJ+xKHho2n+yCrC4TWUWUQuvgd6Ms5hx9AAEBGEMyr7KJK7 +KJuWeJ++mThBksKU5pwTRF9k7CfDShoc2auTTMNyz5KcN35rQ0AiG+4S07Ee6elv +sCSWVD8saw== +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/001-server.csr.pem b/fabric/etc/ca/intermediate/csr/001-server.csr.pem new file mode 100644 index 000000000..e82651bf5 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/001-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDCjCCAfICAQAwejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDEtc2VydmVyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA26nKS8q/8mRcNmMTstUSoTv48OK2vGde +SnRBzW8+YXDZU+nZlRUI+LAVvQLAdOsp6s6zuXCo51hfy2V800RpQ1JsZimTmQnG ++DVcv+H8FjTfCAbiUAa689akzASWhuA0W2fs0yAq29hCRicjRWWzSr5UUM5+MTIz +Jue1Kb9npyJsvAR1FmoY5HAhv7lz0yc47qU8HkSN+Az8U1Nqt4R+88KHHRTHv5pM +0oTG9asI99wQch1s0iutDWsBNeNJYtuL9xCy4a3vwunGUldTcpOFPY63knmkP7o+ +XJpNPHT5wngXE6jCMIQDooTGDN76oTmWzX7LK+4F3dP/G7/+z+iRqQIDAQABoEsw +SQYJKoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREE +GTAXgglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBACsD +3UPwGHbffGyakLcmlI/kYR4la5w6fUBaGVFmhnvQ1GtWBYm1xZEBBEsRMcwcnV4H +f+uWLhPbrN5n3Af+o5e+5BIcxvgz820cV67c08/1uwMCaWUOdY5mYFU1UFkSXydQ +/97gL9rQkK8zuqT6dEWcWYJ0AER+ZBPeSlbNP2HNdfXHKniaZjU8Tswvyxmb/2gG +gb4Tmq7JA7gqvz1A5cXAMHBLfZlaDvA9TuXaqv7gHdPDlIuqioGy43ARp57wFNB1 +Z2lNdDjkwQr9baagX9jDlnoTPzo5ACQtOfORIYPm8GTHe62Vm7etQeergoTvjxe2 +495uzvPv7ssDuup8JxE= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/002-client.csr.pem b/fabric/etc/ca/intermediate/csr/002-client.csr.pem new file mode 100644 index 000000000..1e87d2669 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/002-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDAzCCAesCAQAwczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDGfv6XkzO866Bi+rVZNGHtOjxXZE0HW5rwaxVQ3zMt +k/8Elrlyr6ZuguObyUfLJdnScvirjaGbUqm6XTL7H9yRUKBshQZDtaci6XRm4gq2 +1X7pQ0f1oUmsW5q+dDqbJ8JJ+HbEhbPH7MmZfsTLIASWMKK/pEzTf9t98fyN4LJO +/Yr++PmE7ZEz+YRwGphSupWEatLlfRh7XviihxKcXTiH8Z/qD8A6W8lngu2dHFU7 +VXiBITPwvx/GeanahwduqpnZJNWaCAA7h0MCCatJ01ITGGPgsBCfJWyezBw8CAyL +WYL/dlauaq1q5Xg/Bp8V6HddEy20QypRxdY/kPobAcVPAgMBAAGgSzBJBgkqhkiG +9w0BCQ4xPDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxv +Y2FsaG9zdIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAOeXMaHBB2Wlz +IWW8vd0BxWKtsE8rrd7mL32rivU+mv/ARruGusF8n3kINzE6w3nLCvk0QRAelhK2 +Jp7Ml5ugmS2y/O/y8+vr9iJc2vcd04i1gCzWcjFXZTVNVVIB79Pvycvi6rVWyz5k +X6HlvRrRyf3Sq/52heaHkh8xEWkyDvphUHnorClMaezwCRxfvXgln2riBPdSjNG8 ++Viz5L2N3Rkiim0AkiAb5NMhYzNFtDajdi36qFT3T8ZpwkbDn1eYb0TkoaPr/ITX +EFdsXCsG82QexxLYrA0IC9rygxkHGKErQaLvCQ8X6EgNz3Rsw1F7w0kkiCMfQ36c +k8nxba2a8w== +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/002-server.csr.pem b/fabric/etc/ca/intermediate/csr/002-server.csr.pem new file mode 100644 index 000000000..00e0e87b2 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/002-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDCjCCAfICAQAwejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDItc2VydmVyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxn7+l5MzvOugYvq1WTRh7To8V2RNB1ua +8GsVUN8zLZP/BJa5cq+mboLjm8lHyyXZ0nL4q42hm1Kpul0y+x/ckVCgbIUGQ7Wn +Iul0ZuIKttV+6UNH9aFJrFuavnQ6myfCSfh2xIWzx+zJmX7EyyAEljCiv6RM03/b +ffH8jeCyTv2K/vj5hO2RM/mEcBqYUrqVhGrS5X0Ye174oocSnF04h/Gf6g/AOlvJ +Z4LtnRxVO1V4gSEz8L8fxnmp2ocHbqqZ2STVmggAO4dDAgmrSdNSExhj4LAQnyVs +nswcPAgMi1mC/3ZWrmqtauV4PwafFeh3XRMttEMqUcXWP5D6GwHFTwIDAQABoEsw +SQYJKoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREE +GTAXgglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBAGVv +VIaN7FH3nBxexB9iz9blTw9uvz2PH9g525ebcbw4E7tMWpuJzux+DkIpxKPHsAjz +UkUH/6j9W/C5JjNnGMFwFrdCQIga8FhrOgG+EGuRGIWDk2Mlh1nolOaKSdIguH6a +Ejjc8EFc/VICOn670dJ/LT6PT1CTYFRge9s9F0GxMa07QcBy0aw2RedXOQFSMxd5 +ynCqxn8hhlkRU8SPqz/KH2jZmxFDYjDltMsVz55duVOslyF3RNA8oca0M9y5tgpl +4w3YgF+sjGCQ4fGTcNl6hq9XWF0w9lX2lDrObSR5UWxvHlqskRmkh6tF4N5eZNpG +MCyQNrB3uJw28KPvyLk= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/003-client.csr.pem b/fabric/etc/ca/intermediate/csr/003-client.csr.pem new file mode 100644 index 000000000..d41b35bb4 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/003-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDAzCCAesCAQAwczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDMwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCcg8MIdQyQgc/av7DR8Ulx8ysYWGrT8wIoV515O2Vn +5V3PGNJqosNzOyVmPRhRxN1Bmutj39CA53Jnjb1BgH4e5WEdqWoW2pfuf2fkkx0z +goxRbiOFT1+SmcUKQo9m6PfsAGuLUuW2cvPLNk6SPHuGbcvPkP8jUqjsP9utewVG +TiJto18SbOANg7PuVA76feeYPOitaDaX8kAGTsaNMEz/lriPCwzqrwpCfw+I5QW9 +1u/T52o/O4REKCno1/I3FJpk3LbEAYiGUtXOVlv7/HBj4BfCCpdcIA9P7TYkv1dt +adylT4G1lnXz+OoOUFvvIoFBaNB/x4zDVvIpncpuz/CJAgMBAAGgSzBJBgkqhkiG +9w0BCQ4xPDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxv +Y2FsaG9zdIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAKJoDBGGyGUSN +uQbM0r+TGWV92wIH6AcgU5FsRoMhpNAScha+lhn1+2qUJlgpUAywye0tUzE3PXlX +bjNE/1FNLoIN3X5BfXeDdxtkyQMFYAzctDVSixRHOLU2GMQaYtiecSD/cb3iLgvk +P7QwbXtNNim3eoqYjvyMvP/wVivfjvtgAIquxbtzSuMDrOSwkS57CyZZ+Yvasjx3 +y2PgWCSYaB/pV99s768b9nf3aNQqmYUaEkwYQFBjWQOWpjS9YYFLwRZLGa2tjFSQ +l0hATmzhxfWj/skLQad41HgG/foTXXBI1ZayDqFVYLMI0cy4hOFnCVwHBzVcAjaT +EsxBl5IlJQ== +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/003-server.csr.pem b/fabric/etc/ca/intermediate/csr/003-server.csr.pem new file mode 100644 index 000000000..c371389e8 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/003-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDCjCCAfICAQAwejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDMtc2VydmVyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnIPDCHUMkIHP2r+w0fFJcfMrGFhq0/MC +KFedeTtlZ+VdzxjSaqLDczslZj0YUcTdQZrrY9/QgOdyZ429QYB+HuVhHalqFtqX +7n9n5JMdM4KMUW4jhU9fkpnFCkKPZuj37ABri1LltnLzyzZOkjx7hm3Lz5D/I1Ko +7D/brXsFRk4ibaNfEmzgDYOz7lQO+n3nmDzorWg2l/JABk7GjTBM/5a4jwsM6q8K +Qn8PiOUFvdbv0+dqPzuERCgp6NfyNxSaZNy2xAGIhlLVzlZb+/xwY+AXwgqXXCAP +T+02JL9XbWncpU+BtZZ18/jqDlBb7yKBQWjQf8eMw1byKZ3Kbs/wiQIDAQABoEsw +SQYJKoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREE +GTAXgglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBAIhu +MLS2WGErqzN+15zKdYOoeXZaAGIPk3UZW7G7Fe/yNw5ukNF0nCQBsu97WBYQkXV5 +JY7Ur0Tx/4aplvcUAKbGIQ5FBTzlqQYkuQVgqtDbvWy7NzT7GoLdVsxZm5fFkHqq +ny1l60xRHWnpSyUsAsKvYWPbTMqvpnm2/6JHWs+p3vpaDRvyN66bOi268ozvrVa0 +SlzrkGfm4TIeuxSB5uKIEGDvbAoMK8UEINtuQR+nMa7eOMeDc2cfJXe608dkBZzi +z+cmijYe15OMBuocPNhpJI3Ij5/20HY4VV4QyWwnLp2aATq2QrdijIeIgfRLfe6u +ztzBGpuDSxP5zxgyWbo= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/004-client.csr.pem b/fabric/etc/ca/intermediate/csr/004-client.csr.pem new file mode 100644 index 000000000..8ac89ef4e --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/004-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDAzCCAesCAQAwczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCqBDdOcSnf0fCctQwn+yyjygU3qqx74bQEpNh0YEst +PxbqOrGzkUUV6vIqMAfyQDcEAaXbxh35/W4ms73waN/+swYDkQVbUn31qB7npsm/ +wqTz6NVUJ0r20KFJMVoGtfqO991gl1r/xFT6gc7+v+hGj+6iAuMED7v3xFA7qNRD +8N+iNzq2ArdUX4OfMN0d2y1Zq5sBqicA3vMV91+KDvKfmQRfGFkvyW6Y1S30WDEW +HVCgvmnnw9l8+A8kdEe5/YQbBe5bwdaLYCtv8h6Jz16Ok7jBbrrasYbpcsD8wOI5 +CnyuV7wKcSFO/vcEO/P3YYqL65puKGKVMteyige4/rpvAgMBAAGgSzBJBgkqhkiG +9w0BCQ4xPDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxv +Y2FsaG9zdIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAMTokHy9zmf6A +q48lxaGS+RC0NZlpzwf/NybVkCiAg16MjX1ipLa2hUw0m7CiqGuqZBi5guQISn2c +KPGYp/cEAk3YQh2y5jb8mOvc6t6TW827dJUMkjuEYExhoEZJRPFOSoI/tCMjCjiM +l3hXt4HlErNvMTA3uDACZwiNTQ6uGzv0VCH8+dpTtUkhinYJc1oUy8YAKQr6xvgR +dEt7iRn6FuH0Z9cY35MAR1aFzNIoGcS+UTn/r2BefZNwiyTDTlnXquPL8aVgRkcp +2MkfjH3wia/M/2rtl/vn5dkEZ2jnPqQCMilsV8DUgGe9E6d8Dk7Jeu4H2vo1XTO/ +OIUhslqO4A== +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/004-server.csr.pem b/fabric/etc/ca/intermediate/csr/004-server.csr.pem new file mode 100644 index 000000000..86d4aa939 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/004-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDCjCCAfICAQAwejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDQtc2VydmVyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqgQ3TnEp39HwnLUMJ/sso8oFN6qse+G0 +BKTYdGBLLT8W6jqxs5FFFeryKjAH8kA3BAGl28Yd+f1uJrO98Gjf/rMGA5EFW1J9 +9age56bJv8Kk8+jVVCdK9tChSTFaBrX6jvfdYJda/8RU+oHO/r/oRo/uogLjBA+7 +98RQO6jUQ/Dfojc6tgK3VF+DnzDdHdstWaubAaonAN7zFfdfig7yn5kEXxhZL8lu +mNUt9FgxFh1QoL5p58PZfPgPJHRHuf2EGwXuW8HWi2Arb/Ieic9ejpO4wW662rGG +6XLA/MDiOQp8rle8CnEhTv73BDvz92GKi+uabihilTLXsooHuP66bwIDAQABoEsw +SQYJKoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREE +GTAXgglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBACr4 +joLa7wXzoT+w4SNDZG3SW8++iKEe+niP3rG1q47lWgSIn4Y3xfVUgLu/RlHAfPCY +PSMJx6INsalcqj5I4AWr7t8CVgcXMKbfz98IJJqmQ+DFuE9eJHortDOgELGKzkpc +i9cg6uUUjLXJ0+OLS2tIVHy1lS8UMwI8gV/7J4x05bofDrTWyZgNTH75z7G6QWkx +wC3BnfXHLagCgJFgNI/LPE1AFfhbScx98M+r3kiRJwdJF40NMJzL68ng4XyFScCA +V9W5sOTf0Htu9PqOYQxpKjkHGB9WPpIyQ6NX4kcp7OtRqGg1SFQJZLyHy6TkfEID +EcU1OYQEAwzIanV2a8s= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/ctrl-client.csr.pem b/fabric/etc/ca/intermediate/csr/ctrl-client.csr.pem new file mode 100644 index 000000000..0896bd756 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/ctrl-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDCzCCAfMCAQAwezELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRQwEgYDVQQDDAtjdHJsX2NsaWVudDCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALGXmeb1l8EjH6EbDgY8UU66MFB42THj +A6DwHRaU8TVaGUqM0HUwA6o1oOuDDaq0WGExVTW80UnQC9PoGKO630JXAIh1ouLI +GLCTRwzuHeDdFqh94w/U8bpt8UmdCwM4B9SAbZNWJtzQlR1bH/7NdujyQHhr064h +ESpQeXERt5JD9kEnTaDTBmRBS2Va/piq+O7os8Xdxwm//5CgFJ4mY+Jx2M97brH5 +vo9gWI2lWHo3MrZS2CryNnYv3KETwpsz7FnSab67sch1yg0Y1ewpjXpytNNvPjDN +9FmP2DPcV2pecZur13y5urhv73sOYrFIZeO0c2ZwpPYQ5H11jpEYv0sCAwEAAaBL +MEkGCSqGSIb3DQEJDjE8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0R +BBkwF4IJbG9jYWxob3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4IBAQBb ++MaqsY2rcoHg107Qc+WyxoKE+jCzZIyPTxTYBx7g6NtRQFhPVoZYKdfMRpKRe9Wa +eMsGKbLTBW9WsUsYNNJhQmDDfgWkWP1mmL5Q8ZkC22CPnsarx/8XjERe1fSbK8/g +BvowJgoacymwr2XkfT8a8q/ZVP4htXpAmbJ4tMKxR/YbsbwttOkKlW9hPrGOyU5Q +S6y5eN3PWM+B6VGNLWZC+yowQWyQOtXCWWjbuwHD5sPO6PItZ423E+8h4hyc7BOk +kIJbkJF9uHBsBHpm4qWnRaiB0CDhvn71Nm/I5zul+cpEi9Ean6X1nmp+A96dnqU/ +DjNmWl4GQUmK+0vFi47w +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/ctrl-server.csr.pem b/fabric/etc/ca/intermediate/csr/ctrl-server.csr.pem new file mode 100644 index 000000000..58cf357e6 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/ctrl-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDBDCCAewCAQAwdDELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMQ0wCwYDVQQDDARjdHJsMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAsZeZ5vWXwSMfoRsOBjxRTrowUHjZMeMDoPAdFpTx +NVoZSozQdTADqjWg64MNqrRYYTFVNbzRSdAL0+gYo7rfQlcAiHWi4sgYsJNHDO4d +4N0WqH3jD9Txum3xSZ0LAzgH1IBtk1Ym3NCVHVsf/s126PJAeGvTriERKlB5cRG3 +kkP2QSdNoNMGZEFLZVr+mKr47uizxd3HCb//kKAUniZj4nHYz3tusfm+j2BYjaVY +ejcytlLYKvI2di/coRPCmzPsWdJpvruxyHXKDRjV7CmNenK0028+MM30WY/YM9xX +al5xm6vXfLm6uG/vew5isUhl47RzZnCk9hDkfXWOkRi/SwIDAQABoEswSQYJKoZI +hvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXggls +b2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBAK2KV6DHNg3X +6/5BVvwrw/xShn6JsegGzmryhI5KulPUtZxT1ug8zlOHlX8tocv3A6rnD9U/qb/H +X3zF9InHoMqMNZzM5HAYW6soDNGVdDzMAdUgOHzxhKpIjWP1+nrHzhLuSYZT9cAl +eGgo/75rjF8KP4F7X5ApjQ3lTG+prov+qQBGQKWMwtlcpFvSngI+nt+P5HB1MZhK +uG2h183j5fGOShHabePH/fU6i2XvoQ7MyQSSD2kmarYcyPvVlV1q3+aV+LUYGFhN +FBhcnx3zwJmgGUBRKO2wEGmiwl2NGrsgWFP7OpvGj75Mrf8olrC68nCQMbiXJlAF +iF9lnavVuAU= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/dotzeet-client.csr.pem b/fabric/etc/ca/intermediate/csr/dotzeet-client.csr.pem new file mode 100644 index 000000000..a185c9cc2 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/dotzeet-client.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDBzCCAe8CAQAwdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdkb3R6ZWV0MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtMRtlGukei2+nYGjLbgvSn2JNZO7HGm2Tbh4 +/VfZ9GJquE4iyGoRenNgyEP1LdoBkYlFGrerxO9cOR4o2iPNg1IhnOp96SxPIE5o +gg7pfU9waewlOhULjBwdPDa/cmBIwV80eDX6X7jAsSWtCxnaB7QwTJNRzM0I9456 +QKEpzrOHv9kEUzeaulD/T5eFGRAUEES1h1JdVp+Ay6ZzbE4n208VdNEDV1bm61VQ +5RSbzCRTvoIE2xBwt8YtBlulz4aof/Wm0dR5zzcQqXeNrU4W3jwpzycSEyop5nBo +YrWmjg6r8oZ7PVPTMD+AsBFfzCecrTGCOSdHNWf+p5F1KLvZiwIDAQABoEswSQYJ +KoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAX +gglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBAItwmLYp +5IVaWIKVm7KiNziSAUlETSm3pFN+GSo0k029XIn2jxMJ1nflr5rSTIa1PuB7xHI9 +T8rMSWreJsfRZoNyi+VPom+ZMCy8g7VWBYW6FS6wqg8U+bErLIvd4MyV/Ke6MiRA +9/sqJMHuN+2MC3oWR38O8cgclWur7najVbIX+3P+Ucq93qtrWaVarVzfO1STtNmL +zocAH5BbaOTQojdDzTTMlyrRM2ZVqAfDR9tGprEWxxW1tF4xFk3oh3sEWDhGiH3x +vwXgSS2MoY7U6j+gXqXTODvhTZPD75BCepIItCOOLxUbCVlIzyPGf9YqtTpNIAG0 +xnYiEbwg6noBKR4= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/dotzeet-server.csr.pem b/fabric/etc/ca/intermediate/csr/dotzeet-server.csr.pem new file mode 100644 index 000000000..44d27fbb0 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/dotzeet-server.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDDjCCAfYCAQAwfjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRcwFQYDVQQDDA5kb3R6ZWV0LXNlcnZlcjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTEbZRrpHotvp2Boy24L0p9iTWT +uxxptk24eP1X2fRiarhOIshqEXpzYMhD9S3aAZGJRRq3q8TvXDkeKNojzYNSIZzq +feksTyBOaIIO6X1PcGnsJToVC4wcHTw2v3JgSMFfNHg1+l+4wLElrQsZ2ge0MEyT +UczNCPeOekChKc6zh7/ZBFM3mrpQ/0+XhRkQFBBEtYdSXVafgMumc2xOJ9tPFXTR +A1dW5utVUOUUm8wkU76CBNsQcLfGLQZbpc+GqH/1ptHUec83EKl3ja1OFt48Kc8n +EhMqKeZwaGK1po4Oq/KGez1T0zA/gLARX8wnnK0xgjknRzVn/qeRdSi72YsCAwEA +AaBLMEkGCSqGSIb3DQEJDjE8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYD +VR0RBBkwF4IJbG9jYWxob3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4IB +AQCwsVa3ljYFd8KchIahQacOvnj1MpxqiZS2NdlkA+JfMlfmArPkuBYphb1p2vWY +sfnvoyQ7VtqGsb3zesQKlq4eN6RdmwPA1FjntnurqaNucfTpX9HwiNlmDefHFlTI +0L8MF25EJ7IDcuApThG5qGb1NVYxtaR8SZOfGahkr3xXKI1uHosyVPIET/pDQ85f +bCmBcPt2327S2VW596czfdmO9Aw8AuI9L1BLcKlY/m3xAq2U8g3QG3aB54PvApFl +86BMXfqvpcJL+LGGbNE4eYM3TlH+4JRQlAgYJ//Tep0/QynkJro9te121DYYLvmy +yEj1Cz/atugjFmC1wCcWC5qY +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/intermediate.csr.pem b/fabric/etc/ca/intermediate/csr/intermediate.csr.pem new file mode 100644 index 000000000..a4f453f43 --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/intermediate.csr.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIFMDCCAxgCAQAwgZ8xCzAJBgNVBAYTAlVTMRcwFQYDVQQIDA5Ob3J0aCBDYXJv +bGluYTESMBAGA1UEBwwJQ2hhcmxvdHRlMRMwEQYDVQQKDApOZXRGb3VuZHJ5MSkw +JwYDVQQLDCBOZXRGb3VuZHJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTEjMCEGA1UE +AwwaTmV0Rm91bmRyeSBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCxvUQ+ExTB5L1amNPsvnjEA6Zmq6Anp+FKsV8tTA1TLXva +r4BK9lOlPXMog9xmkaY8HdNfZsdoBHrsFtGRRHXUmBYTdTz4WwatiY9m1oozp+Dw +yHRZnjWgxhA0nJCLE6S2uCp/JvImhPk95PkADtBCZ3yaS7Zf2eQC7qBY9/acc1zt +J5B2KObJBBpUreirJrE7NbOxT9dt8wTP85uR59TGC3lnqOUrTFxbRD5CC1rAwotS +K6jqhtZE9yXseb1LN7xclLmlu9LkmRSzPGhFm4NUdnKWuUcikD8gv4Ge9L4ztI/b +xRZ72ySu/+zoAKkm248nURh/l9qS6A6ljuL6Grtg2L/9yxtzj1COfY6222tHslxN +odQRTUj+1BtAYC02QjikmNFVR0NrBAVCVYdkPUI6LE0sSuzYfMAjTQOEutjpIohM +j+SM3RfHTXRd0xx19rLQ8tabpHDGJGYxAUvgY0gLz3k0XWrrFXhbitaCpQ2Vy8qn +L6LVyFalFtQd7Xq6XSqHXR9wRKtG8BteflitAkuvBtKv7zm5s3yVh00sTSqDZwhd +mVSKVqtlnNaCG0J74qRSmN9G4CL8Kp9LA0rdBcR95UQrpLj2Yd5J6Q6LMUjDt+YO +ELP29fAw6duvJFIsQmSzSAhFxINUKFeF4CoL3zLiRxB2eI1YWeoleioD6utKiQID +AQABoEswSQYJKoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAg +BgNVHREEGTAXgglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQAD +ggIBAADmvwgKE//IQfLADi9rlDUBHS+poNT3na2WKaMwRswdSp0FOqWjoIKZmfg8 +zSMXnszQ7Q4kj+QpzzaHQVBj9tQFLN44NntWMfmU9Eh7gNFZG+0ShfSnO5WnC28u +5c2yxls1G1CwHtivRHdRr7kut7w9IbnPe68Wm0/P1LiOQqQJvKFCVIlmFQCkDJ+A +EWppvfEd51YeHMl69UuUAiPZFPAw+HBxbyQiTtB8hzJqkwyqJEhY7+UbFryyk4KM +E5nUqyMJI3BnPZ943nR9fx8yH7R28n0m7lGQGdTLhxxVB2aZG1ko/AgteODQhSUy +cPrN7jWoE7sSOWOZIGgeGVrkm6TxCytjZZGGjnA2uSLGxHgpuUIqP45YDUIu9vvx +mZXVILbANzZ4kk8evoCyVrXBpX+ODj4HK/ApSb91ZJOXAvczKTP+g7bSbnXWaqkn +kFc//MzVuVC455eym+4X6MulNYAe/SIhQitzLc0l1rHx2QvvDRAnMkeGVmGEVA2D +sJVmPS1pnNy9X/S1O1kgRxVeJ59ymnMidYDOgNcW3pPN9ScJs3lTBN9eYJyTQNic +OClNyP3UOr0bDi3ACIWoPjBzL2JrC94pH5xxfwfm2FMjqOLYudnqQqkYYvWs6I3O +TIyUkMfuZWSlkGrYhMABX9yHaJCJLEFwSP6ELQEfGa0L/ww6 +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/csr/mgmt-gw.csr.pem b/fabric/etc/ca/intermediate/csr/mgmt-gw.csr.pem new file mode 100644 index 000000000..d06cbfb9d --- /dev/null +++ b/fabric/etc/ca/intermediate/csr/mgmt-gw.csr.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDBzCCAe8CAQAwdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9s +aW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkxFDAS +BgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdtZ210LWd3MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJU/MT5Om7hLHOj+u8f+rBlzdx6xcQc399Fd +6kLywH5m+jPc6VWrM0r6B+rrTMvxud1XvrwFQ5RZrYXvGkMqWTWX5ZVQeXOe+UcB +VhFKRx7F7V2mRLQiwgCswzWBsN00pq6Wee104GX54mj9nrovb/V4kX1q1NJrR0rb +EwIG8gceJGT5xt1bHsMpd2QXDqZG6s4oX4ib0QItxs2wNY+7YUuA996Je+6uihD/ +es2m4wkpjKb/snMEE1gResXAzGfLjBAxoCO7UlSC6wlrxnRsvTMYLWV9LuLLc5Pm +zF9crMIU5LSKYIu6uNeWeuetco7QfZmyxsq74UNBlr5Z5tRRGQIDAQABoEswSQYJ +KoZIhvcNAQkOMTwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAX +gglsb2NhbGhvc3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggEBAGP3liiH +ezmKbo4Jy02TBJVhHtJrv2X8QYQ//oYUs8aJOuhMTGP6yD7eUJ9eUR+JEvZQA44O +llSNrCqgt55LctIpGv60SZfpylaQ7gvKBk+zWJXao7+ZYvmrEebQlUY7opgU2SDm +bmsXAEhQth70+dV02XseHeKw4SVFrjisDOrOgjz/JJtYHFyDnf5ec5m+cLSZH24V +uE1Lny8sdb3+6pgxEwTJJCI+zzQDCBRPX9LvQhJBISAEeIn4rAj8yXwF6q7jHGle +ePoVQt9tb9Zy1hIcHAYOofA4PioNIxK2/UhMRsy1XdDV4bidlzAY8Gxctz4E8nGK +xzB604/xUwPyLwE= +-----END CERTIFICATE REQUEST----- diff --git a/fabric/etc/ca/intermediate/index.txt b/fabric/etc/ca/intermediate/index.txt new file mode 100644 index 000000000..3fe6f68c4 --- /dev/null +++ b/fabric/etc/ca/intermediate/index.txt @@ -0,0 +1,19 @@ +V 280515170150Z 1000 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=ctrl +V 280515170307Z 1001 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=ctrl_client +V 280515170427Z 1002 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r1 +V 280515170459Z 1003 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r1_client +V 280515170610Z 1004 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r2 +V 280515170623Z 1005 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r2_client +V 280616192448Z 1006 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=mgmt-gw +V 280806180805Z 1007 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r3 +V 280806180939Z 1008 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r3_client +V 280810192725Z 1009 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=001-server +V 280810192736Z 100A unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=002-server +V 280810192749Z 100B unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=003-server +V 280810192804Z 100C unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=004-server +V 280810192840Z 100D unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=001 +V 280810192903Z 100E unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=002 +V 280810192913Z 100F unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=003 +V 280810192924Z 1010 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=004 +V 280810194440Z 1011 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=dotzeet +V 280810194501Z 1012 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=dotzeet-server diff --git a/fabric/etc/ca/intermediate/index.txt.attr b/fabric/etc/ca/intermediate/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/fabric/etc/ca/intermediate/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/fabric/etc/ca/intermediate/index.txt.attr.old b/fabric/etc/ca/intermediate/index.txt.attr.old new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/fabric/etc/ca/intermediate/index.txt.attr.old @@ -0,0 +1 @@ +unique_subject = yes diff --git a/fabric/etc/ca/intermediate/index.txt.old b/fabric/etc/ca/intermediate/index.txt.old new file mode 100644 index 000000000..d6207c52b --- /dev/null +++ b/fabric/etc/ca/intermediate/index.txt.old @@ -0,0 +1,18 @@ +V 280515170150Z 1000 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=ctrl +V 280515170307Z 1001 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=ctrl_client +V 280515170427Z 1002 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r1 +V 280515170459Z 1003 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r1_client +V 280515170610Z 1004 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r2 +V 280515170623Z 1005 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r2_client +V 280616192448Z 1006 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=mgmt-gw +V 280806180805Z 1007 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r3 +V 280806180939Z 1008 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=r3_client +V 280810192725Z 1009 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=001-server +V 280810192736Z 100A unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=002-server +V 280810192749Z 100B unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=003-server +V 280810192804Z 100C unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=004-server +V 280810192840Z 100D unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=001 +V 280810192903Z 100E unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=002 +V 280810192913Z 100F unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=003 +V 280810192924Z 1010 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=004 +V 280810194440Z 1011 unknown /C=US/ST=North Carolina/L=Charlotte/O=NetFoundry/OU=Ziti Fabric/CN=dotzeet diff --git a/fabric/etc/ca/intermediate/newcerts/1000.pem b/fabric/etc/ca/intermediate/newcerts/1000.pem new file mode 100644 index 000000000..c2e4f6059 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1000.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuDCCAqCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDE1MFoX +DTI4MDUxNTE3MDE1MFowdDELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQ0wCwYDVQQDDARjdHJsMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsZeZ5vWXwSMfoRsOBjxRTrowUHjZMeMDoPAd +FpTxNVoZSozQdTADqjWg64MNqrRYYTFVNbzRSdAL0+gYo7rfQlcAiHWi4sgYsJNH +DO4d4N0WqH3jD9Txum3xSZ0LAzgH1IBtk1Ym3NCVHVsf/s126PJAeGvTriERKlB5 +cRG3kkP2QSdNoNMGZEFLZVr+mKr47uizxd3HCb//kKAUniZj4nHYz3tusfm+j2BY +jaVYejcytlLYKvI2di/coRPCmzPsWdJpvruxyHXKDRjV7CmNenK0028+MM30WY/Y +M9xXal5xm6vXfLm6uG/vew5isUhl47RzZnCk9hDkfXWOkRi/SwIDAQABozwwOjAJ +BgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SHBH8A +AAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAGH1o/uGn8QdwnM9LyoGfaDKCLYZ +p2w+9Bhpbm1RcOgg8Srw6yJHQHrDJgVAH6YYDaueS1TTiUNOUDmHLBuX4AGPga6h +8sxVsB0faYqM82yDXO/wQdw5FmcvBNFpchK5R72L7NSRshdq/VUL+FsWdQw58uLn +s6QDfMme3fU0WRQ5vAkSEm057BKeBXviRT9xNcnYMTlqZaQE2pEdzPG8xicBJNvL +V5zP4HOi63/it2Tv1M2YXVcriBXJkx023CHKZ4tm2enqVofZLyjvzqLTeNuJc0jV +zwjBpp4hG/dNc4p9kl1fQOcd7N6EfBggQy3f89J2W5X4AXBgCjxcubj3pg2q2qV6 +83d45xD4K1HJFRlgpxg26Z/e09GL4yUdST77elv+SKaYNSOuyzOu+IoBv8GHEnH4 +QqbW8/56taQ9bUSGw+r8yvv7uw69bPig1OnAc9hZ4cc4yOVnzW7L98OeKae/XR5I +Ewv1kvrv7ISsYKjSOIGtcQLZ2/xoHsf3xJrZ14viG2OCoRj93P18xod2yi2Vgr2Y +uBdknNjcV3SVv4dsbU8bMSHTThlQM5qrPZHlnbQjncWwXesLCUqeL0O7Tzz6lGT6 +rpD1hgO9R3c9Vmqa5g+Anqbv50YTt+57M5NcLtHTAdfWIOa92LZF8FOpqTE405A/ +xLJv+nDUo0iraA3w +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1001.pem b/fabric/etc/ca/intermediate/newcerts/1001.pem new file mode 100644 index 000000000..e307d47f1 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1001.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvzCCAqegAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDMwN1oX +DTI4MDUxNTE3MDMwN1owezELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRQwEgYDVQQDDAtjdHJsX2NsaWVudDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGXmeb1l8EjH6EbDgY8UU66MFB4 +2THjA6DwHRaU8TVaGUqM0HUwA6o1oOuDDaq0WGExVTW80UnQC9PoGKO630JXAIh1 +ouLIGLCTRwzuHeDdFqh94w/U8bpt8UmdCwM4B9SAbZNWJtzQlR1bH/7NdujyQHhr +064hESpQeXERt5JD9kEnTaDTBmRBS2Va/piq+O7os8Xdxwm//5CgFJ4mY+Jx2M97 +brH5vo9gWI2lWHo3MrZS2CryNnYv3KETwpsz7FnSab67sch1yg0Y1ewpjXpytNNv +PjDN9FmP2DPcV2pecZur13y5urhv73sOYrFIZeO0c2ZwpPYQ5H11jpEYv0sCAwEA +AaM8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9jYWxo +b3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQCOuukYQ6cgstNbbYVe +xJsKRRdLqIdkHthH4dCtOaB5MxIH+n8CpAWwZcepbf6/RsPnsE54kVw1rJwgbWxY +Leyl5iVyuSzQ2NtiJOJAqHiKWLi965bs8e7rHEK/k6AnRpCaqXWZKUMSgFJ1wyLn +B602AE9OHkXgXumNyjE1IVP30BKd4DYOtB33Z3J77F3UIcaDcaU6IJThVO4VmLle +Fv4Vnw8iMvMfAy0FuwAahHEshFW53HW5ZSoi4a8BcwRNy17xQpGKjAOw4naOWe+H +A1T2ayKAGMA9jFcXKn7+lfTSgYdwmhKUGMQTlsqdpHktvBjQUFyPcvMt99AI5Amy +0MNaTQ/tXr6lb3ws40YFOqjD7VKhJcoqcwHqX0xXfI7X0zYNY3DGVTkvUnWTDcle +pF3O6ZKllbL6LKFkJXJRVhqOuomsAuho+vi2A3la/PBcF48z4M0aH8j6HGftzgNe +AS0Ys5iOqJhr1qdBils6hSL84cCsNYyHG+V95jdwNepSOOBqc5+OydFoUjFQScK3 +Q3bjV7T59N11yCMOJzukrJorGtUr/nRdQPcEsCQlvGj60+kx3FEygBIpeiZy5AAS +h7KoWY1Sh2l4YW0Oh4AmeLDY0ryBXDafgAuwGFh7zENLBjDitdpFSuo+d/YksOnG +CR1KiiHDLLh/aqOiR7T0/HKFqg== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1002.pem b/fabric/etc/ca/intermediate/newcerts/1002.pem new file mode 100644 index 000000000..cb3818f91 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1002.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtjCCAp6gAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDQyN1oX +DTI4MDUxNTE3MDQyN1owcjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQswCQYDVQQDDAJyMTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMqCBmQ1w36rpLpVXO+qhcbYvGWh7TiVYC2eD1XB +jSuW1BTeTRV129Obhus4IW81YIGC6dZchH828eQbp8VrgCWPIVbdHvXEFcbppE/V +7BSfG3DFMRICWTyTMHb3bDGhvQl+fiCf4Z3YHGa/JE3emBiTFJK5ohBu1BIIy7gb +25rPaiWcrrrWyCq793UQOFv7pQ5C602xHS4G1EAfn/pwXv/jGQoAn7nQY2pzNHOa +/psMp/TRuqSKoeh8phkYxRzz9GrhMl3DnhiYC8M62mmWUWTxHyimMtXsOiJptM2m +S9Jg8FNb2esdRqJBO7Ms+X/P0wgs90SCYKntXxjttd0PmxsCAwEAAaM8MDowCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9jYWxob3N0hwR/AAAB +hwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQB9KgzI2wIcX/+u1w1T7teTIoyvnDLD +x2X2+ajFUrKsHIQJYz2Gu3ds5VBfWST9vOIDQzv7LWi3uIl/15WkvPUSgdhCzy7W +n0YH7rybxF3cvMrytctg4z4/xflIjZq/7IYsncqNZKSIbZNP46RNzfJfIPHA58rO +Tb/Sq8k57jPOGePOlPXuyUKwaGuKkmGdvz566PY7A2O7y5JmuJx2o9xkSJM9LVRT +X9Ff5ii9PjBALNOtraI7FtNAzMZ/oPiAw4B3MxyoH6WXQyfnd9mLLU3Rrkhl5rA+ +/inQ/HZpv93evu7E4nniwq1bCZTNF4kgIGENdPewWdr+yhcCfm2qYsUC4gStZHCW +FTeV9e7CdfOA5Oj5EsCRWMYUnlNEXwzugBPB9tX7iYFIHL85PWCyuGKx9rtlQ/EP +7DRIoZibdKZGYAq1XtjSHeYzG3OXxq40o4D0f+HkQnsGl5wVF2IIM5ll8tuxKrRd +WiWbEmLFNEJ2wvv63oCaZCKRJxXxpnHif9E+ufOSMTySSyqHMPuSjRuIVwmundD+ +IwGHndcHWSb1hzKPvDUd+OBvM9PZ2A6IOL7XZaRaV0x5O58Fpkn+QU8CXnbbOxRE +D2tysrka4vnHmLDgdM0IKJd05gp8QWpW36Kg0JYckMj0fWWJ1EFPBOJch4HWIYd9 +7aTY4K+wdj1KOg== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1003.pem b/fabric/etc/ca/intermediate/newcerts/1003.pem new file mode 100644 index 000000000..54dbb5818 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1003.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvTCCAqWgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDQ1OVoX +DTI4MDUxNTE3MDQ1OVoweTELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRIwEAYDVQQDDAlyMV9jbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKggZkNcN+q6S6VVzvqoXG2Lxloe04 +lWAtng9VwY0rltQU3k0VddvTm4brOCFvNWCBgunWXIR/NvHkG6fFa4AljyFW3R71 +xBXG6aRP1ewUnxtwxTESAlk8kzB292wxob0Jfn4gn+Gd2BxmvyRN3pgYkxSSuaIQ +btQSCMu4G9uaz2olnK661sgqu/d1EDhb+6UOQutNsR0uBtRAH5/6cF7/4xkKAJ+5 +0GNqczRzmv6bDKf00bqkiqHofKYZGMUc8/Rq4TJdw54YmAvDOtppllFk8R8opjLV +7DoiabTNpkvSYPBTW9nrHUaiQTuzLPl/z9MILPdEgmCp7V8Y7bXdD5sbAgMBAAGj +PDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9z +dIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAWlQc9DCmpQat8kDl3/XN +Tjn2dhbX5GFQTgd7y3n+g44H6Hj2ycQ3Enc/UbBr7k8nK2W+0z9x0QGsFICJ0Gke +9iblVne6RLJBtpnNmGIA+X8NfrOULUm0SYi+yrozVDtN9ydIih7OI4BC7cOlb/KL +ruCWcgJMq0ywQLn1xYJI6h+6SUHK/pD/6OZ53HE6Tr3tNcoGXbf3ccn2YGVm4CJh +lkOwBzKQ9eWMQWkFU381Spz5+yy3/lvsuoiI/GLFj/DxK2jLFBFFCgVSJnMeCudd +jyrWl1VFfIYqkc5sRNbDd8zMz3KFhsjaUvFSwDScBOIMA7uvPlSsZtoVI4ZYYiv4 +KTidpi3fn4hqGv1Cn9UiJvRllwXmK1XaaC68SctG5igRpUFq/nCdGQwOBT8YHtC/ +f0sjr2ibaiuLgPG1xoFWK/cI0c/LFSJIt8hApiLzazvRwJc989kwnFNS0e4Aa3tD +suI+7sIX/JnA3im/6pTcPMBicd8yvdKH2uU40BuPX5Y8UN1VmM7EMP/FFd4F0Mgm +8E+HxNgphCxW4I8jXtbxTdg+sj2D7bfdOw3KaWA6IudTHLirsCYDxj5SatPzDOrS +nOCekXylEM0KWhvoJzwl3Pzk2GlQbImZcguPJ20TraCgQzrJRGTfB1/l+dDrH0SA +yu5RI24xFeHq2b4+EkAmIP4= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1004.pem b/fabric/etc/ca/intermediate/newcerts/1004.pem new file mode 100644 index 000000000..908b2e0f4 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1004.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtjCCAp6gAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDYxMFoX +DTI4MDUxNTE3MDYxMFowcjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQswCQYDVQQDDAJyMjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANTmoX3LVSdcBZaKgy6WXsd9AgGmGXOfFl54tiJ2 +MkM4ukByZ597fLfVvoygPCpvZ8YfdFxxtK37TfXRgg7a/jQGMYNxFLJyywwwwHq1 +Re0SK1obEdKRjBdiBTDb1Djr2eqjRBbkS49N03WWGL0muje89yoiTrqBjP5JUut8 +t2n/T9+OXEc+x6zvvhEZ27Niq1X0VES4c1Ejz7K3b1QBFg2hQ/OAy0kdn10BQMys +785ZMiGgoNv58I1A5AwT8LfKW2aLZftVdQSxmBCbHF3kkZkhNvw5GvyVJFYa4cPu +133iI7y1IZ2ioBbtkHu4Mh8pLGS9ZPIk5BEBYYzFxkhhao8CAwEAAaM8MDowCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9jYWxob3N0hwR/AAAB +hwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQA3XjvA6/hyTijdBdgOuOh/6lk0/aMN +xijrEEdZwpjuLZNXm21srLjUZsNxTxsaH96Z1wZ7VhmI6Gm1dKI+GmhXMuxdGJbJ +Awvy5lAN9N+/wrPWmHU9XPSUbUJvjYkKO8n3inK3d16C08VN+eQ0kGVBB4+lunMG +QCgoY7CLjA3CnapkifEeOl15TRMcsJlTw54MbwU+qohdDfpPbjcKGcy9FzZfWluk +BhVGTSSTrawzwtliyswWd2Uyl72KRSnbjJUPSAU244/s52u/390Bk6hX76966V1Z +OL7kmpIxuzcSAPR6RNgYtQPLI3NLxG8PtkWVF4Fv2e2XHZ0uthyGwS1OGcvK92xR +pgtLchO5u2HT8RYpy7n016CyvbiDcQfbVkQDOgrw/FjlsQp12FgsUwH9akcxmJO4 +lVuuREMT3zEbAJRRtj4+Qs6ox7s8VXguVh1gJx2AOxp8zWnKq1ZrXLvPi8dHAoUm +cTs73LLNE+9Us4RkwfK+jR6/G/O6CKWluklc1R6b1xIafHTuZS9dG+WpCP6XJLbC +tHabYbY0oNWhmmSJO+GqlkXIUe7iMgaiOh8PyGIXQ13GeABwAubtyK7rEepeAruS +167VL7t5qKCDiyMAmIPNo27qhCV0qGwSYKyaV5cSzirgStXXjEDzumCX4p+rF0Nm +fIuHkByO2+iteg== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1005.pem b/fabric/etc/ca/intermediate/newcerts/1005.pem new file mode 100644 index 000000000..eec26733a --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1005.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvTCCAqWgAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDUxODE3MDYyM1oX +DTI4MDUxNTE3MDYyM1oweTELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRIwEAYDVQQDDAlyMl9jbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDU5qF9y1UnXAWWioMull7HfQIBphlz +nxZeeLYidjJDOLpAcmefe3y31b6MoDwqb2fGH3RccbSt+0310YIO2v40BjGDcRSy +cssMMMB6tUXtEitaGxHSkYwXYgUw29Q469nqo0QW5EuPTdN1lhi9Jro3vPcqIk66 +gYz+SVLrfLdp/0/fjlxHPses774RGduzYqtV9FREuHNRI8+yt29UARYNoUPzgMtJ +HZ9dAUDMrO/OWTIhoKDb+fCNQOQME/C3yltmi2X7VXUEsZgQmxxd5JGZITb8ORr8 +lSRWGuHD7td94iO8tSGdoqAW7ZB7uDIfKSxkvWTyJOQRAWGMxcZIYWqPAgMBAAGj +PDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9z +dIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAQkCAkVRZVDN93Bj3w0Ow +/LhrjIO2nRc7hE3Hjvzx7oE+BukFweSNmQ7SFIdSOchYYRjTexdq69s1CjopMWDW +/xCvexaghlIUDSn2QEKdf2WXrs119ZiK9hISNPswF8d/WVfoArqUEG1bxYz9EMy7 +Rbn7RMO97NsosuESpaO3VFLeRRlf79XJ2PGtBONMBZ+vivQiYrffJEXgDicwV0Dl +i1zCttpqoovxV1WpkKYGePYH9eKCsAGVrCksKLL++ZrcTMaNYQz/xbkTJtDx5uyG +e5lO3x0YBYN3grqBxotbmNG35gs+FZkCrbf3v+Bak78RAY6C8lAnTBtnjaYe5En3 +XArAlcDYRnAfUzktVZ24a33kPokUyt8IYvUDt25CFThFmqzGFFr/nHBOjncQ2mma +tycbo0sFp875CmBonfDv3KvGyl3XbuVJG7KMGlNpj2W8BMJamAqYRAsMz7Fh8+kz +D8/4fKYRRJVh0GVX0Xr0VuVwRxlYeJztDa0hwonTrnT6qOJiQaIShTr/hA523Rfh +R3YHWlkiZB/Jb1+ZCrA9udQun/hP9/wHDYqRWx62Q/zl+YrAF1pUJxB2/JNRP5z8 +ZJohaI8dT13W2G28NeHIyv0gTDh/KNVwOWqiopBFJLu1CtZ+UPGaHtqaSMu4QZai +1VC7qB5Kvb9SVaTra/9N/OQ= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1006.pem b/fabric/etc/ca/intermediate/newcerts/1006.pem new file mode 100644 index 000000000..9c0949e34 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1006.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCAqOgAwIBAgICEAYwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDYxOTE5MjQ0OFoX +DTI4MDYxNjE5MjQ0OFowdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdtZ210LWd3MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJU/MT5Om7hLHOj+u8f+rBlzdx6xcQc3 +99Fd6kLywH5m+jPc6VWrM0r6B+rrTMvxud1XvrwFQ5RZrYXvGkMqWTWX5ZVQeXOe ++UcBVhFKRx7F7V2mRLQiwgCswzWBsN00pq6Wee104GX54mj9nrovb/V4kX1q1NJr +R0rbEwIG8gceJGT5xt1bHsMpd2QXDqZG6s4oX4ib0QItxs2wNY+7YUuA996Je+6u +ihD/es2m4wkpjKb/snMEE1gResXAzGfLjBAxoCO7UlSC6wlrxnRsvTMYLWV9LuLL +c5PmzF9crMIU5LSKYIu6uNeWeuetco7QfZmyxsq74UNBlr5Z5tRRGQIDAQABozww +OjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SH +BH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAJTgeIOI7gCNOerPRCbTgHax +vajpPc12QIboMnbDEpo2WgLCju/P9DOTnIusARb1SuUG4FkI7x0AaSM23QSCWIw8 +hHvJg97pXyHbdSBr+9oR2eQ3/kzb0hMQTnsOub3O6Zqju+ZDyzx9OCygfXuacG42 +wj9GhdS1+NgXnImYqkdPl+OtWdrjNRL9VgGnrQSEVsJIRJaKG3AoQxBj7dO0Lwlz +gKkg6+o2iZETT/iEjdszYsHUjnUB5H/T553ruwRH27VV/4TppSGpy6GoOdr54oa3 +H8RDQfEzb2No6zGZ1voKmPp1csUqI0P8CH5T6sPGpmcokLCH53AjDsAAK8K2msa5 +ZQLoh0PunE4LbHdTVmcrHLl009uEoYzH4QCsSo0yA1qImtZah6Pu/NEAFZ2g8BTe +T2kZNm2laYL0kZXQs3uUf+T87uAFEBQ++dnCPVF6v0vAJy6eN4U8m87fncYK9XNq +/QCcqJCOZnEBJyBPaJEx7UuFqxPyXbU/rqk+VOlsaazhvinmgGQOQWFwej6ASf/Q +UTevZTrqVBCV+4YkMSGDCqczhYamsg5UpDqYzD1uHrmYDuHJ+MFGM3TuOMxtxtdr +E6KhXsMrfc0Gwg48x6l2KomhIWK/p0KZ49xlbUWXHurKZcBsZnxOelG4Q0LN4Pea +QXRit0jZCBdZCEReq1hu +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1007.pem b/fabric/etc/ca/intermediate/newcerts/1007.pem new file mode 100644 index 000000000..676b9037a --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1007.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtjCCAp6gAwIBAgICEAcwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgwOTE4MDgwNVoX +DTI4MDgwNjE4MDgwNVowcjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQswCQYDVQQDDAJyMzCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAPU4hhHK5vXq1YjM+/aZ9C49HcPh/jHjv0cfymfO +Ia9vuwqNOkEPlI9UyMNxO5ZepYhynVPyjLV/VqwT0an0ofgGgZ5cV4Vpz3qWnSZj +zhDkcKOuZodm/cezXpEZCQBlG0RHrJmBA63qn+SW/VErnfIHSaEa6/axrwqQholS +zzIf2heIybUu3Q8/n26U1O9UAHEkuif2oikeIzDXO7SdtFOjFtuP+Jfh3BPLL/Xp +xEc9dRM1JxfQuxP+kutxWvdd5MyR5i435jvVO+PnH+DP1yYQkYZfolgxONSl8bcB +GSdYDTmWti8GxhT+ofTW8Dv05E1IwSZaM/gc3Zu//gc/MIsCAwEAAaM8MDowCQYD +VR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9jYWxob3N0hwR/AAAB +hwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQCTrPpWYZT4mw5lT0j00UKyoEWWYikg +eVu2Tf0xQ11v8qpQrVVF9NrX7qdOiA6T3GUln+HaZRxhH1l8jzL5Q75PGGjjBzm8 +LhMrXT2ALk2OuvYVGcGRk+zbmS1X07HQ6+l6S3QPQaATbjoAajJWpDhJUHTBgvxU +/jHe7jSgTD3vjZ/YLQ16uUoiB5nO2TVmCWI8ZzHo3xS753Kfgg6Ybiq+nCtFh5fd +0cgBalEY/TsQqa6YSb1gTrqJ2ZK8Z5rcBjSXJtiQXGQA328E6VTz7S2lrt6b8r5e +s6lgZVM1BVtc7kcHWJ4oiuC8K6zq+1jj5aiCAAGwJesHUBFBdckzgavAbwjAnDY7 +9J4h8oc26hAoIvasgEWuy8L5AH7MF4la3yxc/cbyYTGjIVwAqvtszCttdAhaIDDW ++qKUP+PW59TE7gO8pOq9mkqiBzFzR5qDbpzCen9Ur6mpeUkpQDd98yjHP94L1umv +GvZdCF6IXwpJPKE8sHjhr56luHVWhMIvQBGLu0MeR/8gfLQtwx7Myk91xzF9Fs1G +mYKPDc7zJyxEvTo6fIJSBTHEJIq1hz9Euogx/Scs0X4sCbZQb2yNv62LvZn9vI7D +gIknVkvM0zxuz+RpphJR3A3/7iWsqgvonfCYpvIk8T+uikWcyYS6P4DdA8JNrNyC +rHwG5FHv2xXl2g== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1008.pem b/fabric/etc/ca/intermediate/newcerts/1008.pem new file mode 100644 index 000000000..e4abf9407 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1008.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvTCCAqWgAwIBAgICEAgwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgwOTE4MDkzOVoX +DTI4MDgwNjE4MDkzOVoweTELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRIwEAYDVQQDDAlyM19jbGllbnQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD1OIYRyub16tWIzPv2mfQuPR3D4f4x +479HH8pnziGvb7sKjTpBD5SPVMjDcTuWXqWIcp1T8oy1f1asE9Gp9KH4BoGeXFeF +ac96lp0mY84Q5HCjrmaHZv3Hs16RGQkAZRtER6yZgQOt6p/klv1RK53yB0mhGuv2 +sa8KkIaJUs8yH9oXiMm1Lt0PP59ulNTvVABxJLon9qIpHiMw1zu0nbRToxbbj/iX +4dwTyy/16cRHPXUTNScX0LsT/pLrcVr3XeTMkeYuN+Y71Tvj5x/gz9cmEJGGX6JY +MTjUpfG3ARknWA05lrYvBsYU/qH01vA79ORNSMEmWjP4HN2bv/4HPzCLAgMBAAGj +PDA6MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9z +dIcEfwAAAYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAOn/Jyjj/rKt5jWMJaO3Z +43az271UyWZ1vXvC731DpMAlC3B4jnK4EDOH31WtnoYz5dx457SjX8SjJfuaKX3u +PLs+ArtjVx3l9YNzaEKzPtTE1yCkGvrEH7o12c4SFQXmHghJ4HipPXp92bNw7KQE +CRqkMSSHQylZ7al0GV9xyrN04SSMZtbeC0TuulfkQwlfB+gIGhdqc0AOiILzhAyx +Iw89LlVAANoGhkoOFad7xiXJjkvwwE5kbkC4ZoqivJ1tusTbb891tdSgkvYxescE +iaydBx0h9X7CkHNMobnf7ILcinyeDzKcGQmmd3P3zNkOgvpwWQtGsxkDMq5mZpmD +/2LcfeLSQJXuxlO+hCWGS7+bqAobHPL47nd+X5+v9P0kNWsLWBmy7EMhkTM1Sn1r +h1dpDNkEKVrPnmj+yfrf6anj+WqtcMGQB4x8hRY4nutOfwgpSu8vD3NVVIfc1Z76 +KptSce+uJqPyS+AVHbVsOCFvIKw+wV86DxVEFUko09/udWfH+lyYlqj47Ap7QUy4 +apUi66hm+OSXgjldV10b3STO71XC3GeuT06XZ37iASYZpvadWNARS5dFzEtKzMJw +ySE9BXW+MoOpLQ0rCClQI5IViTe6QbhmSax9ltTOxp9bUsuqw5mFBdc7wOkGTpWL +93SupGat5JJWhDRkDKAeLuo= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1009.pem b/fabric/etc/ca/intermediate/newcerts/1009.pem new file mode 100644 index 000000000..0087b7943 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1009.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAkwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjcyNVoX +DTI4MDgxMDE5MjcyNVowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDEtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA26nKS8q/8mRcNmMTstUSoTv48OK2 +vGdeSnRBzW8+YXDZU+nZlRUI+LAVvQLAdOsp6s6zuXCo51hfy2V800RpQ1JsZimT +mQnG+DVcv+H8FjTfCAbiUAa689akzASWhuA0W2fs0yAq29hCRicjRWWzSr5UUM5+ +MTIzJue1Kb9npyJsvAR1FmoY5HAhv7lz0yc47qU8HkSN+Az8U1Nqt4R+88KHHRTH +v5pM0oTG9asI99wQch1s0iutDWsBNeNJYtuL9xCy4a3vwunGUldTcpOFPY63knmk +P7o+XJpNPHT5wngXE6jCMIQDooTGDN76oTmWzX7LK+4F3dP/G7/+z+iRqQIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAInGp9pJYVCUJErrsart +M5vtK/Mm2qBpbpcdj8Gnokh3ubL5rY0MjpOz5AWj0c4wFgV28EdAncjXEor4VOEI +JgsbTm3STNJnA9BT7vAwNezbl1N6jOTh8vUrjaSx5AsWVbah6nZX8rfc9db/m+zd +iYedN0VJF9Fi6wrK2CssDkbYc6PNrK/lhgyWAcacQdthZTWmqmObNToAY1FNk6m0 +OHXW0ipuRFqNRUw6snU9+SqbcOnCqKtpAan+YfNj8cXuiytjxGfQVpQVsp9zdXqX +efkc13iKcJ46GLkWcWrjWKkVt3EjUbaWENECmz4/Nd1LgzmEaTwVUCxtAlVnKk7P +oW5dgJQpWk5chP0XidyvwiKf2iC/fck+drj7f+iJDd26pZ1LFvlA7MO9eYu5HpWQ +tL4dF2MnubU98Hg3m/ryygLZh7I2rvPsx8/g1m8LYhiJ4QFkXKdZ8IQ1daqUtUmr +ooH++0C6r9fNgyEbhGMungcC5DHP58CofDJuoUyYhUyNpQgq/XWKx23epQiOgnJm +rb3AB8X3TE40LneNfKdS+BNq4q2s/GYrI0BfmZ1BXjH0YgR0iLv1PZl+0L7++RHO +wE6kjuIs64UCkzIzaNByVUuAVRRqZUV0j6U07ONovqhPSNwky4h8VBaTLHWOfK4Q +k0H8p9E549WS07pfmKIgoKvh +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100A.pem b/fabric/etc/ca/intermediate/newcerts/100A.pem new file mode 100644 index 000000000..3d5835602 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100A.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAowDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjczNloX +DTI4MDgxMDE5MjczNlowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDItc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxn7+l5MzvOugYvq1WTRh7To8V2RN +B1ua8GsVUN8zLZP/BJa5cq+mboLjm8lHyyXZ0nL4q42hm1Kpul0y+x/ckVCgbIUG +Q7WnIul0ZuIKttV+6UNH9aFJrFuavnQ6myfCSfh2xIWzx+zJmX7EyyAEljCiv6RM +03/bffH8jeCyTv2K/vj5hO2RM/mEcBqYUrqVhGrS5X0Ye174oocSnF04h/Gf6g/A +OlvJZ4LtnRxVO1V4gSEz8L8fxnmp2ocHbqqZ2STVmggAO4dDAgmrSdNSExhj4LAQ +nyVsnswcPAgMi1mC/3ZWrmqtauV4PwafFeh3XRMttEMqUcXWP5D6GwHFTwIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAKoioClffib8U2RlOXTD +oPc5FWW6pPQoYP8Acy67G96Pacudy7wLWO7TI1s5KQyceyz5ZNmITtfXMgxJbCJv +Gd36fikb2iqlfMM89JWz17M5wTpZ83DRNLqDEL5NkEy6DZmnMd/w/saRvc2ZYsul +CaNsK9xQBgwesYMC80stTzpiw8p1sDh/JDjMDq+NodNtxgFN4nm7wIbmRRS2V1si +jfSAPK3cMyMNEGp/2C5ELpEq2kbHX/J4GOlva5c2g6Jte6sz328pCSmklNnGpjZL +HsSvXp4YUFwlcsF68qg9z/XRMvjodxQL5Jgz7Wz07lSIkqmRjZbECXXmdkyml3+E +zB2xIEzTbSG38tKOZ9bJ0KN7wPVUgZzIxX96/12a2q+fVVtKkVVQ/Yd/M9CpP8Yh +PRAznJppvYxdVpGIFyyD28b1K9TH3Hgo6W5GzJCqDf2tr+xVsLyoFu+ctBj9OKoT +yVW99v23d8iNiB4Kj4CIXIu7gbp4iJ1FbjBzubDVQnjwTkv3KnW6oOXSPN6rAg3+ +Pa/fizIAw5ScWg8IV3jrVrQm5XOr6GN5dh42f9Pd5BSjKO6uL5asKPD6hptAKdYz +DTs13LHwtimowZuhZ0+fmthHMLTCygkXUwLmDEka6Mqivhr4zdBjVY1qQefOjm2W +i8pWD20RqNu3F2f0HL6JZQ1/ +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100B.pem b/fabric/etc/ca/intermediate/newcerts/100B.pem new file mode 100644 index 000000000..6b3a7b081 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100B.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAswDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5Mjc0OVoX +DTI4MDgxMDE5Mjc0OVowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDMtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnIPDCHUMkIHP2r+w0fFJcfMrGFhq +0/MCKFedeTtlZ+VdzxjSaqLDczslZj0YUcTdQZrrY9/QgOdyZ429QYB+HuVhHalq +FtqX7n9n5JMdM4KMUW4jhU9fkpnFCkKPZuj37ABri1LltnLzyzZOkjx7hm3Lz5D/ +I1Ko7D/brXsFRk4ibaNfEmzgDYOz7lQO+n3nmDzorWg2l/JABk7GjTBM/5a4jwsM +6q8KQn8PiOUFvdbv0+dqPzuERCgp6NfyNxSaZNy2xAGIhlLVzlZb+/xwY+AXwgqX +XCAPT+02JL9XbWncpU+BtZZ18/jqDlBb7yKBQWjQf8eMw1byKZ3Kbs/wiQIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAHyJ6NQTPGg/CJTC/9nb +KHaMra0aFLnvNUFXCiRsLXY7VNx7Z8HsWkm6TrTsTPIu3deMxfg4Rvxc0vDDsl2p +YU3rjUNMpzWZQXj2mNO1cPdG30fAIWNCc5qiGXoI2eJjEDM5QXyLMVqneTg7PQ0g +cAnf6h6FLmifhdR5e/VZPEG9mEhubETevmIq4lSqQ1lopMjihT1fC9l+a/WaQXxa +Ic6Uq9vHdGONFgvjsnjXN8py/zKw303mnAXOEHiaznyxJ2+5UjZ7IYxcO5p6soJR +XkkHIv/WyAM+kfljvzVjxx2jTwV15L+399T0x8g5F0fjwd5c0H05JcOfpVB1gPq6 +HZ+B1wyRs5xNQtYJ9On8KIW1Y21fzjUhKglhGrZ3148DB9WJ/Fk7CJUEuTk37E1L +LIhI4/ml1fvE2VNmPabI7xjMtFRaALRKmAhGINnI/guAKHYJqcSQIBIJfOTrXYx1 +Z2SrT0sUre2toVBNzyyI68m7eGOYaMCTOUL5gCI/SXf3r4LKhNitVow8Rw3Xt1il +9xRxZ6SzTs065kjJys4Tuw4a+NF21PVq4dD/HVVabQRDf/6OubjAARo4FyomWsyy +nkWwIoZi21e2F+RM5rnuXUuZ7/eV6dJPfBQ2E4y4E0qE+vfNZpMi6OnJ1xdTfTx+ +z9e60k+pZ+r/ozXQ2srE4ZvZ +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100C.pem b/fabric/etc/ca/intermediate/newcerts/100C.pem new file mode 100644 index 000000000..c2b965de9 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100C.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEvjCCAqagAwIBAgICEAwwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjgwNFoX +DTI4MDgxMDE5MjgwNFowejELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRMwEQYDVQQDDAowMDQtc2VydmVyMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqgQ3TnEp39HwnLUMJ/sso8oFN6qs +e+G0BKTYdGBLLT8W6jqxs5FFFeryKjAH8kA3BAGl28Yd+f1uJrO98Gjf/rMGA5EF +W1J99age56bJv8Kk8+jVVCdK9tChSTFaBrX6jvfdYJda/8RU+oHO/r/oRo/uogLj +BA+798RQO6jUQ/Dfojc6tgK3VF+DnzDdHdstWaubAaonAN7zFfdfig7yn5kEXxhZ +L8lumNUt9FgxFh1QoL5p58PZfPgPJHRHuf2EGwXuW8HWi2Arb/Ieic9ejpO4wW66 +2rGG6XLA/MDiOQp8rle8CnEhTv73BDvz92GKi+uabihilTLXsooHuP66bwIDAQAB +ozwwOjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhv +c3SHBH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAEPPwvTShn9x9E0um/Rj +HNjGzcuShd0E/tWlUHnn9F1i6Bz0SlbYngbxIiQUxgmraRtzH5wH4Z01xE6vdA6S +unckj1XyhwGTV+pufxSkRk6Ox67MZjjXOst36hyQjWNsNf3xDaPFxAvxqWqaMJdf +mHAUlDiXIw7kbuZM/eBGx97wNf2F1YPSnvcfPir5ZhGKg4K7ZIlV0Opvemwgqf0s +vjkQPRpnILfrInQbOlnFEDMh/tMN6eIEGPDX1MjmMS9cckr5ZacevrjlsNyuM7C/ +QrVuYHFJ9Le1Eum6GjzMGILUxADoc3r1UgDfaysIaru02lefnhfNeOYixjvV3Dkc +rGH3Vtwc4a8M85qh7oKlJ4+f1e3Qn01LmDlD8Y99a30ebbtfApCCUbHJerXoG9Cy +J7hcFyO6ZBcTHfVWsHjAoL2oojdo6smbf+7pR8+pxAdnExRsI3sioaw9nnKPCOz2 +T6NzlbvCts3d2Tpi9eJg2t+uxA02e+qxC+MIk+/xlZ41VvIkUsB4wQzK5nBpziCs +wGCzR/C0uHFUVPubQd0oB5Hh09Z4Dbff28m1N/Aqkty8SQGwz9sJAWVDN60cBGIj +f+NhitZf6ERhoZUDODuhcuNmCilmZn9inPIGgtMVhtWpFXIB3eSoMSHKUWyFeOfj +mv9NYvwrZkt0PCGOxCtwXAYV +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100D.pem b/fabric/etc/ca/intermediate/newcerts/100D.pem new file mode 100644 index 000000000..89552507f --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100D.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA0wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5Mjg0MFoX +DTI4MDgxMDE5Mjg0MFowczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDbqcpLyr/yZFw2YxOy1RKhO/jw4ra8Z15KdEHN +bz5hcNlT6dmVFQj4sBW9AsB06ynqzrO5cKjnWF/LZXzTRGlDUmxmKZOZCcb4NVy/ +4fwWNN8IBuJQBrrz1qTMBJaG4DRbZ+zTICrb2EJGJyNFZbNKvlRQzn4xMjMm57Up +v2enImy8BHUWahjkcCG/uXPTJzjupTweRI34DPxTU2q3hH7zwocdFMe/mkzShMb1 +qwj33BByHWzSK60NawE140li24v3ELLhre/C6cZSV1Nyk4U9jreSeaQ/uj5cmk08 +dPnCeBcTqMIwhAOihMYM3vqhOZbNfssr7gXd0/8bv/7P6JGpAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAmPpB0t/nGnpJ8zS01256g0P1UjwI +GOj8DF4XhQVChDk+9VYEg1DIvku52m1F7Wxgp8q2ELTEjnywZrK/VD4sos0cWuID +f4DYsUqdM8gGHc5uVY/eubWtcWAo7qegrfdq+S6MD8DqdiCnBTe5xruWBaZhm9aP +lwPpVSqDVTGyjV9wLB/mNc0xOEYg0fenS0UbHZAlDWHHCZQmkMnW1bU07qxKfu0i +/1Ok0H0w/kEIxv6LuSSxPJQ9yvy9eB+2HypdeQl4kuZzue/tXrLn20MhWHPaJZjr +BUDcLYg7Badd2lyySh4T5eSY1XyEPogHCx8XMWRixjkaWgdZpriVgf1g7wXc6W6G +fD9pxQyQ1pq3zL9rbWWzyrmp4gwOsAOq1HwmGJtHI9qVU3VxSrbZCF9bnYTRdIpS +UNWMqOv5uuYspKzcYl2FFdGUd3QQ5ExSsFRZ2+xjfDyhlPOOuJtb3RK3HoY35Gjg +DWB3mU331H+UtCE8oCs5nKQcS0iH86D+CnqJkkvQHSVH+QV4JU202x+Ym0q3aaqy +AuE5Nj5ybnrN/WsL3YYkpbIYZAvGWnvHGYOLjs7caLBwv2vcfibAsPX4m+OhJfuU +0zCzTCS6fzf/Jg9R1p7392CESYfJ34eVuda7ctWZrMXFyGsxeydCO2TTdDjRolO/ +tToiRRetrmH3JcY= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100E.pem b/fabric/etc/ca/intermediate/newcerts/100E.pem new file mode 100644 index 000000000..34a874604 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100E.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA4wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkwM1oX +DTI4MDgxMDE5MjkwM1owczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDGfv6XkzO866Bi+rVZNGHtOjxXZE0HW5rwaxVQ +3zMtk/8Elrlyr6ZuguObyUfLJdnScvirjaGbUqm6XTL7H9yRUKBshQZDtaci6XRm +4gq21X7pQ0f1oUmsW5q+dDqbJ8JJ+HbEhbPH7MmZfsTLIASWMKK/pEzTf9t98fyN +4LJO/Yr++PmE7ZEz+YRwGphSupWEatLlfRh7XviihxKcXTiH8Z/qD8A6W8lngu2d +HFU7VXiBITPwvx/GeanahwduqpnZJNWaCAA7h0MCCatJ01ITGGPgsBCfJWyezBw8 +CAyLWYL/dlauaq1q5Xg/Bp8V6HddEy20QypRxdY/kPobAcVPAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAAA9Str4WlbxQaKuzZ38glD9jjkCE +tA9jwCJnNv5uh1o4z4RFLPK4s9EsY28g13LRKTm5ft0ndO4ofTb0xUDH9ddeTjsY +QtXrzrh79MzH9IIIyej8YubRqeVeQdR0a0RoG4IACziaA3hrZlIDbM7xxrXKYVzC +dvV7epVT1bO4TrIf96/JwHBBtbWBi+GedOtPgAxlFQ99nvlPEeKIEmp9kv111Ot/ +WpawpVE6EALDFAS7rT3zU2t/9qHtWb6i6QMGdJ/WKsHVOOMRMhR86tYKxYz1M4Ux +NI/2GQCdYSmbmzAdKKWWrrTCMal6MjhPjWnFyjXUgUkSuIyfJ8U5MQ/0hI8BF3K5 +SqH96WVoKGud0ohPC2bjdZ8XqRHvBU6nhJ5pnNA8YjMevombwMWOAVpYjfnCJK39 +hODeOiwdDm0AWDJ18wcAnyJH+aX6L50y2BWhE2Gc90P2kqA6YgRCAy2rwBRvDNua +yPGSyHJfNbyQ8e6tVbWDEkIQkP1A0uDD3SxoWNcxOeAmtQV6Ig779pxZ+GqHKR57 +bJ5wJjFJsPRgHz/ViP11IMffldb+6tvMKR4iVZO2eZ9GPqIwxXF154pKR2lL+mvV +3I9kBfkYLd4Z61hTmCAJpZaIlVTGsjLAU2W56m/OOI8piaZ/UUMMrFiVtKuFp6kF +OcrllxHkVaVgFbA= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/100F.pem b/fabric/etc/ca/intermediate/newcerts/100F.pem new file mode 100644 index 000000000..e3c7588b7 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/100F.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEA8wDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkxM1oX +DTI4MDgxMDE5MjkxM1owczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCcg8MIdQyQgc/av7DR8Ulx8ysYWGrT8wIoV515 +O2Vn5V3PGNJqosNzOyVmPRhRxN1Bmutj39CA53Jnjb1BgH4e5WEdqWoW2pfuf2fk +kx0zgoxRbiOFT1+SmcUKQo9m6PfsAGuLUuW2cvPLNk6SPHuGbcvPkP8jUqjsP9ut +ewVGTiJto18SbOANg7PuVA76feeYPOitaDaX8kAGTsaNMEz/lriPCwzqrwpCfw+I +5QW91u/T52o/O4REKCno1/I3FJpk3LbEAYiGUtXOVlv7/HBj4BfCCpdcIA9P7TYk +v1dtadylT4G1lnXz+OoOUFvvIoFBaNB/x4zDVvIpncpuz/CJAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAqfnYmdpLwOKsqoh8EXMdsa9AQeRy +MiqZEpyA6tCkfthC1qzFDr4L5Gb5eXZI0Xo0yYMTvMx2oaP/zu81EEvsj6L5Tnig +eaZqqm7DlUp42FQOdikv2OTctuZ2y1QAsE4+zStawE7il4ED5C2cTDbVBZccJa2X +jl7WB4505Ucec+fmgX7lQB99/NF5Ca9cCnvhb71waTPsV9GTXTBYPvd44N2g/o7y +Wq/3ldqMkdj2TrPTWjVxXfDD6CtHCAyXpJmab6tHSbiquYyHxBVgcJgxrlxxpH4U +/xdYPjRHqXh02q42Pm0MwIp05NdcxcUv+H+9YKlqr9Mz7zZdbjb22QbfZr+59xwd +V4QW+EhEV0OWcAvkbULosSolm6EZX3QmfET53rZqlXf2FSTSF+J6DhQ0hCIIk86D +5Sd+gHO2xPieFtFD4DdcW/RLa7a5csIFg919zpADT3XOc9bM27gcBc1uc5h9Ov+/ +KzGRcnobI4f5sRgAJumLMgVF1iIE94QJpC07zmzy6t9GEJ3z2t24v58Ai6h4THg0 +CTa7FCZzcvNX7dTu3tueS23NJtQNMq89sOJiyrXFi/8+sgnqz+ed3QMtPpU6j6bf +WSXtC7GDkumLYMxnQm7v9eVjO4EkC+2dOfIZBDI+nrGXXw0OpDptXgGQEmFC3ie4 +2M821rvVbFSjhDU= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1010.pem b/fabric/etc/ca/intermediate/newcerts/1010.pem new file mode 100644 index 000000000..1ee1af0bc --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1010.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEtzCCAp+gAwIBAgICEBAwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5MjkyNFoX +DTI4MDgxMDE5MjkyNFowczELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMQwwCgYDVQQDDAMwMDQwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqBDdOcSnf0fCctQwn+yyjygU3qqx74bQEpNh0 +YEstPxbqOrGzkUUV6vIqMAfyQDcEAaXbxh35/W4ms73waN/+swYDkQVbUn31qB7n +psm/wqTz6NVUJ0r20KFJMVoGtfqO991gl1r/xFT6gc7+v+hGj+6iAuMED7v3xFA7 +qNRD8N+iNzq2ArdUX4OfMN0d2y1Zq5sBqicA3vMV91+KDvKfmQRfGFkvyW6Y1S30 +WDEWHVCgvmnnw9l8+A8kdEe5/YQbBe5bwdaLYCtv8h6Jz16Ok7jBbrrasYbpcsD8 +wOI5CnyuV7wKcSFO/vcEO/P3YYqL65puKGKVMteyige4/rpvAgMBAAGjPDA6MAkG +A1UdEwQCMAAwCwYDVR0PBAQDAgXgMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAA +AYcEAAAAADANBgkqhkiG9w0BAQsFAAOCAgEAe6zSSoa8HWmjvtV6+aktA9vUgrHz +uUtw3OFM/4Gg2U/M1pDirBobh/EZwDqeTNqVFLBibMAWj3V0mND+SLm0V36hOFiE +lcnYSJXYoErJ7LLScUfRjPZdu9JhNl8DoQ8NgbHewVZhecA1MbUsTCbSNsufREM8 +JYbd9+C52N4hqdfxuT+8imGE1Tg3/9CcldukVC4XNBhSYskhy7zMf6UNvTpBH3EO +434fraxCjgnPiQJq5S6Bq3Oq1Kbr0o/l7gLNIzz/KlOBJQsVIPExFEMQ7kZQzDQh +AmvuoRJEWB3fdYYmxGPOB/pJH8OIjyzcyC3XNDtyz51alXD3G40GHECO0Gnb/Tvo +kKODky2nPWrlVuoY6R6bQsFojsUQJSifz3p6jUE2Cpv3/axg0juumJKaaDJqoxVN +Bp1vGS+IIcj6nZEyfuUCRkaBAssUKXC2i1uTeoyovsBkjOef9fyclN5ym9/fsyUV +AnWxwpxIrfG26AeV2nenRLFUqzvP5xJNF1HBwijmOdYn2tlBImxv8ziRe7JhUyxE +fXiqFyEgaPDJ3SgDEIzmYd1tt7vqzpqJHQOe4hJDoga5q+qX8IJOJEz2vy6E9sm9 +tGdVTvJG0422Hlk6OZcitD+zavn8KjVQ8mMszbm3LurjBYO3830KhAWrOiN6f8gg +X6sIXw8/4UKo5d0= +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1011.pem b/fabric/etc/ca/intermediate/newcerts/1011.pem new file mode 100644 index 000000000..a6a2f8ca1 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1011.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCAqOgAwIBAgICEBEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5NDQ0MFoX +DTI4MDgxMDE5NDQ0MFowdzELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRAwDgYDVQQDDAdkb3R6ZWV0MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtMRtlGukei2+nYGjLbgvSn2JNZO7HGm2 +Tbh4/VfZ9GJquE4iyGoRenNgyEP1LdoBkYlFGrerxO9cOR4o2iPNg1IhnOp96SxP +IE5ogg7pfU9waewlOhULjBwdPDa/cmBIwV80eDX6X7jAsSWtCxnaB7QwTJNRzM0I +9456QKEpzrOHv9kEUzeaulD/T5eFGRAUEES1h1JdVp+Ay6ZzbE4n208VdNEDV1bm +61VQ5RSbzCRTvoIE2xBwt8YtBlulz4aof/Wm0dR5zzcQqXeNrU4W3jwpzycSEyop +5nBoYrWmjg6r8oZ7PVPTMD+AsBFfzCecrTGCOSdHNWf+p5F1KLvZiwIDAQABozww +OjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAgBgNVHREEGTAXgglsb2NhbGhvc3SH +BH8AAAGHBAAAAAAwDQYJKoZIhvcNAQELBQADggIBAKAGn986vhFHlxQ1bG0+hQdu +vrSG7E45Y81AuospC7ABm74Zny/zg3choeVTcoZoKmZhKAPizX5LMbkML6x/kjQt +jbZFeez6Q1LAn5IdiDlLUXY46/HubClF/gfAaJcQP9h2CQfqhqsl5eVqfbcz3fSB +MMZYuAs6DcaJcS2u6rIXmH89F69bs83o0kdiMTFyC35WXzh1d0lqbi0p29Bc5Btd +eEgbHEqyP2oYASCI7hSeMhIu0kRhUsGDvBER6Sag6k/L7t6lrQ/r1EP2ss0ycheV +ShdCaX3oikH9LFk9hSBTGf0HGxwku54GFRU3ch+EeRHd6iJj6cVKuPV7cpmNFSF+ +n34byUC01fbjLhlszJIGIt01R+9CercU8MyoD7+TmzY90yu1PFZ7B9jDqkkUqSyQ +HPE/diq0Is/RoI0q5HL6bqk+/HwQQ9XcvCsC2kbijtGVMMhBRl7m2GMyiFtWlhVu +trNWaOj9tXlbBIkERgDWRteCkMgU6zjbKvqepQC5WAkvu0LnhpbhTXqjaNGZqBio +1j/BKp+6ozb1Jamv4C0/rmEMBRH5Z+X9vqDmkAwLJb7wZySrFBQchvKnPnwHUQv0 +JniImSdIKbiAakU4v6wMCft6tDvDmWKuluN3JmAVz00y9/vbVwMFdrRQQjlePDBR +XG4LbZTH8lXKIrLKDCEW +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/newcerts/1012.pem b/fabric/etc/ca/intermediate/newcerts/1012.pem new file mode 100644 index 000000000..ae28a9b83 --- /dev/null +++ b/fabric/etc/ca/intermediate/newcerts/1012.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwjCCAqqgAwIBAgICEBIwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEp +MCcGA1UECwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNV +BAMMGk5ldEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDgxMzE5NDUwMVoX +DTI4MDgxMDE5NDUwMVowfjELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENh +cm9saW5hMRIwEAYDVQQHDAlDaGFybG90dGUxEzARBgNVBAoMCk5ldEZvdW5kcnkx +FDASBgNVBAsMC1ppdGkgRmFicmljMRcwFQYDVQQDDA5kb3R6ZWV0LXNlcnZlcjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTEbZRrpHotvp2Boy24L0p9 +iTWTuxxptk24eP1X2fRiarhOIshqEXpzYMhD9S3aAZGJRRq3q8TvXDkeKNojzYNS +IZzqfeksTyBOaIIO6X1PcGnsJToVC4wcHTw2v3JgSMFfNHg1+l+4wLElrQsZ2ge0 +MEyTUczNCPeOekChKc6zh7/ZBFM3mrpQ/0+XhRkQFBBEtYdSXVafgMumc2xOJ9tP +FXTRA1dW5utVUOUUm8wkU76CBNsQcLfGLQZbpc+GqH/1ptHUec83EKl3ja1OFt48 +Kc8nEhMqKeZwaGK1po4Oq/KGez1T0zA/gLARX8wnnK0xgjknRzVn/qeRdSi72YsC +AwEAAaM8MDowCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwIAYDVR0RBBkwF4IJbG9j +YWxob3N0hwR/AAABhwQAAAAAMA0GCSqGSIb3DQEBCwUAA4ICAQCD/bQOYXMhywqT +UsWgLvNsff5R3xT2ddn/ECN0KJSGZKYnPrCimWAVIEz97gVgPQneLyYz2aAEbARR +IFvnKt4saXb/jbTNThV43IU4kTlpU7B4VY0w6RjmMCwpCwokIeRLNIU2SmswApoW +isVBIeZ4LTdByKy3a74rPk8Nbt8pOa27adWoLrO9bxjReZ/RqeWwSVVOgVyiVkTe +UadIADo1HJoFouyvjJsNG8E9B2V5KZ9FgdbJzGKKlMkHd1DoauNHTcORwcLz8G2X +rf9yEiFYQKlgYaHpR7YtblVR9DiWtT4Nd25JeCiTZ+1/npj2stt+ZnjaZcFkLh43 +1Lw+HlD4eR4MLPEvlcBvmpTJcTOCY0ZL1GLK+Ip1dL90cseIBmON07zIqCNKLqUF +baovuK1MTG/Hs/y5N1KOBFcc18O4F2DpSW0hD7AEFjEArs4mUwGrlqroCNjGo4K/ +CAXVltyFQqxWcPBzNYG/HKgYe6uatAjPirQrV5p/8CXOzXP7nEFF5t1tppilseib +Amb8ClAby+//S6bDsvcaRNTtYVUJpv04ScjiT9/s1nBleGx5RMsz062JUbL70S9j +bjBYvseajIZzaMIUL0zc3wNFOxUVCTaDMxt5GxO24YI8JBrRjPbpzLesJ5iMmjZq +3hgAjgNwSNau0M0jKoqYSoJgBGnZaA== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/intermediate/openssl.cnf b/fabric/etc/ca/intermediate/openssl.cnf new file mode 100644 index 000000000..27c12472a --- /dev/null +++ b/fabric/etc/ca/intermediate/openssl.cnf @@ -0,0 +1,144 @@ +# OpenSSL intermediate CA configuration file. +# Copy to `/root/ca/intermediate/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = intermediate +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/intermediate.key.pem +certificate = $dir/certs/intermediate.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/intermediate.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_loose + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +req_extensions = v3_req +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = US +stateOrProvinceName_default = North Carolina +localityName_default = Charlotte +0.organizationName_default = NetFoundry +organizationalUnitName_default = Ziti Fabric +emailAddress_default = + +[ v3_req ] +# Extensions to add to a certificate request +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning + +[ alt_names ] +DNS.1 = localhost +IP.1 = 127.0.0.1 +IP.2 = 0.0.0.0 \ No newline at end of file diff --git a/fabric/etc/ca/intermediate/private/001.key.pem b/fabric/etc/ca/intermediate/private/001.key.pem new file mode 100644 index 000000000..26f7bc8cf --- /dev/null +++ b/fabric/etc/ca/intermediate/private/001.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA26nKS8q/8mRcNmMTstUSoTv48OK2vGdeSnRBzW8+YXDZU+nZ +lRUI+LAVvQLAdOsp6s6zuXCo51hfy2V800RpQ1JsZimTmQnG+DVcv+H8FjTfCAbi +UAa689akzASWhuA0W2fs0yAq29hCRicjRWWzSr5UUM5+MTIzJue1Kb9npyJsvAR1 +FmoY5HAhv7lz0yc47qU8HkSN+Az8U1Nqt4R+88KHHRTHv5pM0oTG9asI99wQch1s +0iutDWsBNeNJYtuL9xCy4a3vwunGUldTcpOFPY63knmkP7o+XJpNPHT5wngXE6jC +MIQDooTGDN76oTmWzX7LK+4F3dP/G7/+z+iRqQIDAQABAoIBACRdzdISdQjKOMIA +USiQQg9TgHlQ73PtoRyudp5uRmOXbUOJOa6G1v9lF5Q9OmOg80Wehv6yeiQi62kf +GjVX5B1zLeMUCw2RItHA8+QIo9WBV1Na4GjjVFw+MvZb5BfcUo63e+vQLYhMG1zF +6f75QV+kdw0Rwq6eYv2T6thIif6PU+7AYn0Nm7bi6Goy+p0hwqUJWQCYcbBPBLUV +MifLY6Jq2vqtL8tAB4Bl7JQ+jWBeB2OBYt0T0fKkQZ/ORn+MxTKuDv2YBlkmJqKE +QLLfzEOi9o49urihqBKqBdwZNIG2FHsq18GyxfVxLTbCwtptvD4gHlJ49EaCbmBs +37klEKECgYEA7+gzUakobfjam6NxF/k2Yqir9yyB+VEaIwEIgaf6c/BgOy63iNI9 +Zignd9tB4BLv3S2dKwlwZvq9shoiaMKB/ZzmwOggjuCzM6okMLPxj8VdFp17t9MK +aUpW5Lw43+cuvDHwMfArd1JI3dt669zpyUgjY64s/KoXJ9mCnJoQK4UCgYEA6mX0 +H5IPxVWaWodqdQwwK3pOccZ0JVzkesCfZYWRy6Sd9SlkyPHNhfcbdRYXA0NQh5ru +z9vr2qj4DM511wECkbcw17Li7vEc9FKH59OGj/q8mHtVAvjsaAKYJa2zJPi39hqZ +fcmnOFv1D5jgdPM0Il6zZqzRiNBLPHV1HDqLrNUCgYEAlUqrPOMGbMES0Q25oBCO +noCWWv+QdmTY3fWTpJOy0JlCWTHuNq+WU88jGHwSF23RZJMxHgoGr57Tk1SeGxEH +sZoFIwCQ2jjMa5cyZDhmV3CbSCqCRdeHwBPp1PeocPU9aRGuhnUNp3hGLgGaEdLs +jTxeAXbvOeBi/oJlvCxHab0CgYBgDmHpoii2XKtBmCbnSpRe7ONCuuoT+apkJ5Xq +u78QrihRNKJpurXXxXlKFUBfBPH2cGaXZe+UjxP/44flETPlVSY97sAS3VpZQY0S +UtvdGwq4jio7apku0olZP4KfjxGMWEA4jS/q57xYpPSu2I+v2hE47W982qdKYnQY +mmFs9QKBgC1L6Et/tcHLmxvj+K+/2f15KvjvoTeQxDniEcRi5Op+Iupt27Bjxsuw +uf7yD7vkUeTMdjnHsoG458l0/a5cC84WQ1o4gZXRiCCY4pMhe58qMoTRgbayzVVg +zhLHUuK2y0XsrZOCvcl+2LZeWrPVDfj0xxmjYlLsE/Rzo8DLe0L2 +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/002.key.pem b/fabric/etc/ca/intermediate/private/002.key.pem new file mode 100644 index 000000000..a1b709ee3 --- /dev/null +++ b/fabric/etc/ca/intermediate/private/002.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAxn7+l5MzvOugYvq1WTRh7To8V2RNB1ua8GsVUN8zLZP/BJa5 +cq+mboLjm8lHyyXZ0nL4q42hm1Kpul0y+x/ckVCgbIUGQ7WnIul0ZuIKttV+6UNH +9aFJrFuavnQ6myfCSfh2xIWzx+zJmX7EyyAEljCiv6RM03/bffH8jeCyTv2K/vj5 +hO2RM/mEcBqYUrqVhGrS5X0Ye174oocSnF04h/Gf6g/AOlvJZ4LtnRxVO1V4gSEz +8L8fxnmp2ocHbqqZ2STVmggAO4dDAgmrSdNSExhj4LAQnyVsnswcPAgMi1mC/3ZW +rmqtauV4PwafFeh3XRMttEMqUcXWP5D6GwHFTwIDAQABAoIBABWsgDgkxp12TQkB +vxOCeL7igPw5439OLVjbGHTAKmJrqojhvFYdf9rJR/kWvVQdSe+ExkpVKLRBDm9f +BdYN4JOtbhbrX4e9KgbR3vfs7qaQIU9vHUhg2B6N0hPBtTSD3t8c1jsXLk5COLEd ++ncDg/yyStMKKaleaKUT6zPCuTWOoICaqL/afp+99c0CFMSpKIv14I2UeOdoWjfN +Gumh79iMpOt29+xScQp2EngrL0feMMfpIXT/OUB676RTqLKZG8LLBG8ZdDdFb+fR +0Elo3O1Z45ZlAlYKhTsSlHdKFxGrwn5kca1RNHKyKX4djWnMwS43lG5W3RXVXbJ/ +6+fkpyECgYEA6Wpsp7L0tB3BZpTNK5NrRZqiLb+TQUD3cRXQU87BpdoDeXyhm/vE +iZdFY0rQrphiFtYPpiidlY5uyOuzjsrJke51peK1H7pafENFCGOIPm5BC1udF2/o +U85L0/avjAUGzSpnshev1aMH0FCgjvPyIAlx0RM1QoqpkjNMq+aDs1MCgYEA2bOh +TnBoP1BwTGZli2o9z6iWivsXQbJGRdzfSabw8uUBRcMBjZbMANGPW7wgvdoiJqMh +Ptv/QmUceaS6G0Km2Wnw5TrnuNdCjnaV+6W3LJtLyvyufkxmVbd3SKIfwFq4cjav +6RGwnrBN+ura/WkA930Z5cpKmVX58Hv3qaaFQpUCgYEAqDIpM7qvvG7Io1vMcH8d +SJ3CCcdHnDjtVU7LvOh7AEEWSd+2MMl+eUtJE+CgeX+TBzOfOTOBQnjNefjmfZnB +IGg93Jh9vewyMeLjhsT6M0qNklqk23OnbWR1nbrgCrzAhuzspheNfBurkL/Ywsok +ilNj8a2urlFvGcvfjutfscMCgYEAndUny5CfY9fTsvBCCpOaAKW/jz9/mve/DwOV +Nva7lb4F8CfzRk3f1XAZOW7pZftx6wU2Izaol+Bqhp6w9vaZtOKj7e2I9m/KJzM+ +hdWdOc/VYXNUpuiJAPgkmRpBXtnnA5c2bgmPPV2hC5ud7T9lngiq7/h7oTO+I2Yd +Jng+AQkCgYA05H7kUJslPITr8mfRijL6Y2PZmBO4TSrVdPG3KEgn11bE4lvRhnx0 +suWBAgy4ecQ9bY+EeiusrGrGeWqW7dVwxpNdphp6ZACn9tOiKsISsYTHC5K5GXOZ +OVymINiiYL91lyMSRtt9y7Lj/cLDh+lKUomiD/ZZpBeLgcLbpmEAFA== +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/003.key.pem b/fabric/etc/ca/intermediate/private/003.key.pem new file mode 100644 index 000000000..7ec6aa107 --- /dev/null +++ b/fabric/etc/ca/intermediate/private/003.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnIPDCHUMkIHP2r+w0fFJcfMrGFhq0/MCKFedeTtlZ+VdzxjS +aqLDczslZj0YUcTdQZrrY9/QgOdyZ429QYB+HuVhHalqFtqX7n9n5JMdM4KMUW4j +hU9fkpnFCkKPZuj37ABri1LltnLzyzZOkjx7hm3Lz5D/I1Ko7D/brXsFRk4ibaNf +EmzgDYOz7lQO+n3nmDzorWg2l/JABk7GjTBM/5a4jwsM6q8KQn8PiOUFvdbv0+dq +PzuERCgp6NfyNxSaZNy2xAGIhlLVzlZb+/xwY+AXwgqXXCAPT+02JL9XbWncpU+B +tZZ18/jqDlBb7yKBQWjQf8eMw1byKZ3Kbs/wiQIDAQABAoIBACYTyDcegtgFPNQz +Hol08jFOv4VEvXii/jtiVWVRFfKY0qG3oDlhL7uxAABHjMsX4dw8HFhH8ynpJOQc +j5aH9CcAFwhoVu8Ibz4OsO/i+o+1iv2kle+wx8easV01pD2dH/PChmd223vvq3Ac +3jCllke2Hod49xlY2s/fGUqzSy03I7NDGoktMn4B77isRcIA7lenCDI2H1lW6CcN +G+f3RW4fbagnK2nlZyN6BzPY+89cd6zRhjX9SnG58VpFV9uAYfmLrQfK0NiQWc1d +VBO+eq+lkkRlLqyKhM4Z5sMv6QPc9WIBPNoT9TOM/CPh+J6rD0JSV+DkutV0SXss +F0wCwAECgYEAyQ2KXfIitU1ZfSRIf78N9Js6OdmKbRvrDZvsJ0oLUA/yk7MIbxop +WwAk5NmgdM+gmZuce6zyI0DyrGqCSRPxqRUhLjBsSMflygF8ytY+8qbnFILmDTaE +L5Ena3Atzicd4YOrNWvXuugGDTwpfdoRikqyoKEWt/63L5GYHXu9xwECgYEAx0om +6Y0XPfd0n28J6jPAWmGADVi10G3tOeX/aVxFA4dj/KlS1xYAFJd+3DxuUVeqNrqm +VuFa+Dalk8asM5ei6z5NFvis35v7dWwkLEwbBxSzGvpuWU7zU5jFtrbGAS+YAMzC +Pr9kUFAezBvIpEUMHe0NXnHyy1suWzNbT9JpcYkCgYEAkRZiadVY0rlVAQf0Aawg +KAr1A9ZHHOHuyE1jKB849rfreEbUqUiZ23/JIBUkw+cpoHA5hs6RlntCJMZf6tin +pjsHTMvI+OS4oQRdyArANl/Xlme4GITk82auqcu0Yna8C4f3P3/pmInkBB0MXDPI +QKITMfPN702zaHKK8YvgsgECgYBXdimhsjQTE/jwx7CYQmIWyFeEg/w3HydPk6sG +OGJpbA/roPwkPRmH7/zS9wqLVGf1YPEDjB96c7EzK6wDcHclus/mVvi3oiM3o2A0 +uKnb76+zFVk8hLOxaojK6Wf4uUSChVpyY1jJDoCVn1PtFAh/UbveSS//I2Myz1Ux +sOxp0QKBgC0Nuv++rjXHL3+08w30RKDMTnfRb+sRJYNnKR9JbT5GP3/XFaHT1H0K +Az+MKnl21DEefP7IUCtp0rowFBJFlqt7podCtGVeeDxoHgc/2si1Iia20ew1Agbn +UdlPwor5aMg5pHIY3VXKrxBS8CJXo7r2sgNvX8ZCHuqqTzkBnKUt +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/004.key.pem b/fabric/etc/ca/intermediate/private/004.key.pem new file mode 100644 index 000000000..34522afee --- /dev/null +++ b/fabric/etc/ca/intermediate/private/004.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAqgQ3TnEp39HwnLUMJ/sso8oFN6qse+G0BKTYdGBLLT8W6jqx +s5FFFeryKjAH8kA3BAGl28Yd+f1uJrO98Gjf/rMGA5EFW1J99age56bJv8Kk8+jV +VCdK9tChSTFaBrX6jvfdYJda/8RU+oHO/r/oRo/uogLjBA+798RQO6jUQ/Dfojc6 +tgK3VF+DnzDdHdstWaubAaonAN7zFfdfig7yn5kEXxhZL8lumNUt9FgxFh1QoL5p +58PZfPgPJHRHuf2EGwXuW8HWi2Arb/Ieic9ejpO4wW662rGG6XLA/MDiOQp8rle8 +CnEhTv73BDvz92GKi+uabihilTLXsooHuP66bwIDAQABAoIBAFUyQai8SniPUpyk +mQ/b7RWyoYSwsThu9O+yz4kZy/JDgC8l9HCAZndCQdHkOccqaKdIUB3enJzuY2lf +ftnfJAgVG/ljjaSipN4aPkplKQo/9rsHPQernQQrrfbolS1xubo0+SlzDzXF47OY +ourDrhjV/YYQHkSlwdK5/F65Do1wcI/x6UFcszb1nls7Nji5KM2hWMcM7re+V4wG +P5I2NCTMiFVoFyoJUEX6di6wmN6erlffnVAS26PaDFt7jrtwn76sPtH1k/to7PoY +GUWli6L6DIrT1EuwOwwWdYQj+GHtpHS9pg8pP9iLn5LPEDEXoS61rkxzbQGscOou +6TD9TkECgYEA3iYLD/UHCmOQFlTC12WXBFRxqLwANHybS4aU2niG1O0RqWEebskp +fwGPcp9wvJzf1uiwKa4uyOJrEPmqu4VAg8l5SH0tIloQ8JdZI6uqQVCO1W2i6u4k +b26633geuT4VPKKL2LlVjrs/jHNq4sNJy62eu3hYSXZPkh8AKvNLhOECgYEAw+yD +Jr65DchC4s+04GetW/iW2nhxkSJzUcuQm5fEAtPZACnmBJts3hiqd49AnoDWCsg3 +HotqDbTIp7kGmPV4XxboHLhjsEOS/2xyghOLBo3p86a7xNPYITaHwcGMclFV8CKa +q8kofTJaBic4BH0IgQLmRXUYDypd1IDG6TTO2U8CgYBJfA4mvigRELRGHs3BENLu +1LwwU9hBhIKebitpRXtcjftMq1q0zQhUAgEgqotRaRdGcPxtHThOrU87c0s98qtP +rOLYzseSWHbID1imSw/rwSkugrDkw9f7oIZii8ql/lpqD17xVwVtTJWN8VQHJRCR +NqKOYxXZXzCdJnIYwxhVIQKBgDAAra17gymOTFz32PA2VrI2+Pb0FZciorCCuJ52 +k67BquQwX8v3LLhJwNJkRcfP9yFTJrYUIFrVVWhKnAQz+FcL7LjEsKAKHmT4dCHM +mf50HML2sgCqisSwcJiXTEriBLU+NTkrowDxqj7hswbef4vkYvjXlJp6ndyn5JRU +vO1fAoGBAIED6UqXk/YR3DAYJdlSrKPejz8JPFHYVth2Xc5v1qoECRkPQkNZBirx +XZAAmy76Q+GjGW5vQOPyHMfKQp5RlhmKw0yueYCRQg01VhejCwFyXFdhmfPjfrlI +Bhi7yVGt6SyCyPwc1qeAhwgEY57N+aWUKhk3yIGR2C8gcOLxlFmy +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/ctrl.key.pem b/fabric/etc/ca/intermediate/private/ctrl.key.pem new file mode 100644 index 000000000..9c3f681cc --- /dev/null +++ b/fabric/etc/ca/intermediate/private/ctrl.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsZeZ5vWXwSMfoRsOBjxRTrowUHjZMeMDoPAdFpTxNVoZSozQ +dTADqjWg64MNqrRYYTFVNbzRSdAL0+gYo7rfQlcAiHWi4sgYsJNHDO4d4N0WqH3j +D9Txum3xSZ0LAzgH1IBtk1Ym3NCVHVsf/s126PJAeGvTriERKlB5cRG3kkP2QSdN +oNMGZEFLZVr+mKr47uizxd3HCb//kKAUniZj4nHYz3tusfm+j2BYjaVYejcytlLY +KvI2di/coRPCmzPsWdJpvruxyHXKDRjV7CmNenK0028+MM30WY/YM9xXal5xm6vX +fLm6uG/vew5isUhl47RzZnCk9hDkfXWOkRi/SwIDAQABAoIBAQCrmGxguZT0TVfW +dynJ5KY7h7P/TYWvqkZrTxcMJsYaYwBlBEK3uLkR0de3OF4QP0nWP7Cxx8wBokCL +dIu6SGpI03/0WpYUwnr4wpW4bKv6BiZKj7jCJ2OaW3j1RATMC2ulbKJz5p6OZgxu +3QnBTg5Dby/UK3vRmKnZVQDCu/fAHsajyGKas7590va+/2CDhkCAusQx4bkUuKsr +uXYbbZhxs1HNRZFNTz3bb5g9kRUiT31EHjW6fTykxmAm0XjCbKqshJb+/zZ/QiUx +JF1xwCw4uIVJ+G+jReZD+7pfXLXbtKdDdJJmsKMEDg3MTEuEGGxFrshRXU9kzRBT +OCKejAAhAoGBANwl9ricyY4TX2WOJw8ezI/YO07UDOCR2h4rnkK0ryC3kzkBtPP0 +zQ5OYvzet6kkwSmipn44mQR7hU5aPktj1lMd2LinjVssmCQHxbrmV+qrX0mjwH1a +W0if5B2ipe7IDdRKLaS0VlH41jBuFAbnsijkPomOBKyOsyWFk6R+0DGFAoGBAM6D +dosjm+yT42pigXn3njI1gHfUWFW+9io1ySqOhcB+eUBgpB9ML9yApfTMymOoLBaM +eKVVBt+IQwKnNI09x5gAIVQPxA7IySRh4Uj0lyeE4ZacaHwQfrIWxjUABMJppGpx +zYp/Bnf6gakUy9HZUkE1v/OUYnV10i/3/mqBWZ6PAoGAN9saAjUlnnqj1ax/lIKH +/GcshQ+gRMo8wTLn8JzPYkmxfOFF/C+8Z0jULLyFdNDygZHXFGdfy5dbd0nGTHKE +SopkFlXMs7lY0Kt4K7eNzui0QIbfq+5lAsQuqKY/25m+iIJZmlR3Ik00aw1C342h +0mY2x8fUv8NlCLwffbj/MdECgYAl8T9xdvxp7g4FeM3DI/ybyvqsiYYlUu2VecZZ +HFB0uof6jQb6fRv6DmTvYkT5JGfdSLfN4J5fqYBuV1wvax9lzPhSoobqFHfoSFeE ++PNgnmh4LIqB6OHuRILsL/Gv6or7x6b1ADunBY6XCywbhSs4sfBvh17Dp/8TMyQ6 +W0Ok/wKBgDyQw7XvEcMdEF76m17oQL3IxsWn6BE/CkC9cW2IjqZOXgE0Z34hR/OB ++I2zeOQ7tZYI6w30tDgy+Q44b/OBp/11K3HjW3RgjKcP7c5cXHKPzUBQav8eEctG +t7CK2r1edMB8tufoEAGQ60Engq9WjsrIhgoYNOnliol7x8N+NnXO +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/dotzeet.key.pem b/fabric/etc/ca/intermediate/private/dotzeet.key.pem new file mode 100644 index 000000000..2f44e796b --- /dev/null +++ b/fabric/etc/ca/intermediate/private/dotzeet.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAtMRtlGukei2+nYGjLbgvSn2JNZO7HGm2Tbh4/VfZ9GJquE4i +yGoRenNgyEP1LdoBkYlFGrerxO9cOR4o2iPNg1IhnOp96SxPIE5ogg7pfU9waewl +OhULjBwdPDa/cmBIwV80eDX6X7jAsSWtCxnaB7QwTJNRzM0I9456QKEpzrOHv9kE +UzeaulD/T5eFGRAUEES1h1JdVp+Ay6ZzbE4n208VdNEDV1bm61VQ5RSbzCRTvoIE +2xBwt8YtBlulz4aof/Wm0dR5zzcQqXeNrU4W3jwpzycSEyop5nBoYrWmjg6r8oZ7 +PVPTMD+AsBFfzCecrTGCOSdHNWf+p5F1KLvZiwIDAQABAoIBAF1T/O9gE+8wpvVS +9Ripu2DOJ4UN3NDykzjVQUIrlU/jcA3v6W1ntdZus00yKOefYqftI0yD/58RpZ+n +vpfBXF2sjcYiGxfD1KZtVO+xG0OjO/qz/RRbwTZ5XW61JWq741RS/xgBZl79WB8d +wJW2pybLFRS0CsueID8PxHaRvrAEin7x6DFHzXr5W/BIoEYEynG8qX0M+BtWNhDc +eTo5ZGR3er/NE3SAesYkwV3Pnt95mCdB7HHSAOwj32JPsrYaes5a12LN5P95I210 +enlTssg/C2Y7A2vIuN61GU0zAhn27hdq9KEkQNYprUDmLm4IvVkWSevEkEyZkj13 +4uLIJAECgYEA4KIX/CULc7VNR6JPzcyA5yyzDPbGcvoQhk+wh9FelCL8c9nmK5b1 +0Grz3ayKE3kbcqAeaoKXMEXlVh1DXwYEeqh3gNvrTPmhzpqZpW6ue+EfFY/ho6Ly +9hOfyABzAP0eVi5366S/0dO1p1qcJG4bn4CMByb5wputLZLuYwEW/4ECgYEAzgJF +iFpbfn2ftFXf4JbB9Ebe5adoQZQ53dTi3mPOU+kEllo+zLk8zqqC3WWBY0IdIOhx +joOzq4gV9Kxkl/iHd+P6q4BjMxap93gInBZye0XagHXRep0I9GUvaX+dHCl1rRbC +atMxLftnStVLtx0bfRW9VgNE8Qa5pSzkcAruXwsCgYAJU5GNXXhhQHjJ7ZpEoCYF +8xwoAKLyqSFAglSA/xdfLSiwIq7kxmrEUXx4iq5c6p1SIAXDRFLEpVJFRgfDDTvo +X9A+YGMfmgm2y0Jv1O2XpRwmSAgFREG0J9Jtel9L/jZhO6Ks/PUd4B1dqmxrMssg +zzSBI4QhKVeCWeRd5fCvgQKBgBPMEBaMaGJ9fA1+eydAFZ99+AmlztUOg4kX3j10 +5e0WZYR1Y7eUzY0mwbC5AnghcF8rN050xZ1kVIfQ0VHxZkNVO0+j5OSR9v97H4iw +d4v1KIxTxi+8S5IA7096HgUIzvA1UbWmWgGLOV/to3sTZwLcRfewFL384XZIHCPQ +SRwFAoGBAJNmm8+jq7Tyc2PeXCXYfPPtM0jwbf9WQeQfmopjzKErrxe2Nbld/wop +wWRWOdrNfT/YYLXZUp0V0a1YOPXXTwxKTBmLg2gz61K1tDACN15qehvNzVUPl1ZX +viM/YndV/fFriz+N5CFou6KYjoxxFJgW4yLlwhzwxvHEjGIrnd4W +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/intermediate.key.decrypted.pem b/fabric/etc/ca/intermediate/private/intermediate.key.decrypted.pem new file mode 100644 index 000000000..1b2638275 --- /dev/null +++ b/fabric/etc/ca/intermediate/private/intermediate.key.decrypted.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAsb1EPhMUweS9WpjT7L54xAOmZqugJ6fhSrFfLUwNUy172q+A +SvZTpT1zKIPcZpGmPB3TX2bHaAR67BbRkUR11JgWE3U8+FsGrYmPZtaKM6fg8Mh0 +WZ41oMYQNJyQixOktrgqfybyJoT5PeT5AA7QQmd8mku2X9nkAu6gWPf2nHNc7SeQ +dijmyQQaVK3oqyaxOzWzsU/XbfMEz/ObkefUxgt5Z6jlK0xcW0Q+QgtawMKLUiuo +6obWRPcl7Hm9Sze8XJS5pbvS5JkUszxoRZuDVHZylrlHIpA/IL+BnvS+M7SP28UW +e9skrv/s6ACpJtuPJ1EYf5fakugOpY7i+hq7YNi//csbc49Qjn2OtttrR7JcTaHU +EU1I/tQbQGAtNkI4pJjRVUdDawQFQlWHZD1COixNLErs2HzAI00DhLrY6SKITI/k +jN0Xx010XdMcdfay0PLWm6RwxiRmMQFL4GNIC895NF1q6xV4W4rWgqUNlcvKpy+i +1chWpRbUHe16ul0qh10fcESrRvAbXn5YrQJLrwbSr+85ubN8lYdNLE0qg2cIXZlU +ilarZZzWghtCe+KkUpjfRuAi/CqfSwNK3QXEfeVEK6S49mHeSekOizFIw7fmDhCz +9vXwMOnbryRSLEJks0gIRcSDVChXheAqC98y4kcQdniNWFnqJXoqA+rrSokCAwEA +AQKCAgB0u1swcZO2bCY4dBrrZ4UlJ0iIMbuzj7yVM7zQoRw3Pq4TSCQ4F2OEKMGT +IFcGPi4xWV1TUMsx849PswTcJVxFzcTh7qOmcRIHs0qtPcXyexVuzhgsK44JE0vd +Yd5EmRgasQWoEMoEplyTW+h1M0Vv90uMgqE6fn4Ttuk0xVYAFnw3fT6Re/dmmf05 +FCa1EWpg+roTf9565ZqJgPLxdpL1pt+LRw+LylD11/ITqiVmZ97cjrQXo4riLHeJ +wcKive5F15+9y4eMf0VrGgdZf/NW65wChZjEiHwNY/kbjp3Ek5fPvLcxjRGgpZDQ +Jm7xiE2Sgt5WHkN9LE9CSH+lxxy8PBNTjNHmgtP1+1kovCqLp4pXH3zOvipGlsBT +cJ+9KZnb3UlNYzsxd8NLuWKC7o/lJ8iivEZe0+/z8Ou9LP65vwQ7UI7q/NEG23cV +5KisnwAXLxZf2V2whTl0ALVaWW56Oy7MFuuxayviHXQGifYYNA8asFMXKeNFnKj3 +tqiuCdojYNqzz0oulva/VpVmu6zMvpcvPsIXp9RUMsV/f+qZeZ5Fn1Yjr2nC6IDk +mU/IcqmFZFms/0JDdTHuOVn4UzgFV3Cagbb+fYn8CyfEM02lMJSZAPYfYYcwob7P +daUWKPdvdte4b5DXviJ13bhtT1/FtS82uUnWvSwqkUSZbkpYAQKCAQEA2yq3Baso +rpTJyv2TMY7UNC3FhmuR7A2XH5rooBCMkuavixQ3VowDIsX5/2IGSYZAzaYwHSz4 +6Q13N/taYSoG5nQK3r9z943lfHuepKhjshAI8jjXaGCLLUDmXL6aEyEtNq74RmzY +5QtASys4hgIM3j5jQuBvFffKiKGZQRoEbwVL6mnOcGSg1QnPajGo1TJga0BhOrmz +LRJA5QPa7qEmFcWeT5SC/VKlfyp67imZgX1d0CieepO+CHA3T+hJoeAGzwb8I0wp +wzwLsH1kLrB/hGFKlU3ygVR3ejkd0XkDMBTMNFpbYfgUiiqPsSzf63PD3qV/BfiT +U8SvkRTRGDIxCQKCAQEAz5wzp4+OtndprajGX0sdXrf0bV4cjy2Bv/N9G6zoPxfg +GWCaTZeIsYfGoyrA82Vy7ii8jpI2YCOJPEbOSawt19ZKrh9CY6QmI+sYQWMvKfNJ +ttsU3/LQVHoP/2mVEU3B6EG6WUxpb7zJKax6p4dUMeQPflYJmQ367FJlRZZwFuXb +u2zjWVBPAEjAZp5XvBJqypsuruCmJjrF1ePohu7AlThtM1c2bvnJs7WV2Q3h7MGb +f4z69/7siNs642fMuww0SSbGaH7LtmLOvicrJ76yh4NTpP1oV8hOpViMLp+o0MJb +co/D3zxBa49G21bMDY2Uf9KKPsYEKJcD5ZcsyXItgQKCAQAXfHFWgyv94WXqgdf3 +NJYa7VjAeeCOSjqKoYASPxPBXkUrg0QW2zQu0sZijq+by25AW3HGfp5B4zaGYkIi +LW3F3mOX0S5tNeCEwX6TqJPebgd3ZY332nivpcfJ4ocCS8jblk52xY1MpjMCmyQY +gDm+yzK55PEiioZCtAaHSnF1MD0dZq8/rhjqG34FpEKybg6VD7Ybo/DGgLFBmXMp +pU0+ggnf/0s2OFgR04yO3xhbHwMhnmi1PAXeQ6A5yOuzFB3Gq7nzUmMbT+D0zcsh +kbpohkCG1W6KW3HeQCao3u3vhhsH9TLbwcj5sWvqkaOBSMuRnWyKSEQJcwdZZcCu +dhp5AoIBAQDG3r/0UGXKj9ShTzzG57M4mkn/wdjlphfWAa3kJttKJNq8NHdawD9m +n8M9ZaTzAkj3rfoBMDn6GdBJ9yGAHPjE+jcLWFJGFGWcnoTbjeEN9Ei2amIyq+u4 +IDzW0xLCQpPuoZeaFsIhENw5mUjc1ZtnNylIQa5r+KJWYg80e4jfxkuX3BRj57Pl +d8smAaPVOmclsUUkq3k8wavk2a5SIr5DsouYVICGCayXAuiJxOyX2FXV9vwpNv7p +ked1Emdg/a3QLN5+FoeZLEkSiX6jUd6+RKSJNV0QSYZciNevia0yXBsxQFnGq3eX +SuX7Ecfha6/GSa23uAMfxpkrAocaaM8BAoIBAFJiuGZ1/R09vib1z5wj+zb73j8l +kesparGDCxEesQ5rcnphO4rpzwE6PYX18TkMfsKS3CzCwpPGKVrUZoPmx+dDaVfX +cJOgqc/ALniumucpiYh2UEyqTZzurInEbZ5EPxmfsjIcyd35b+ZkAKSXHH+DuE5W +iUC5EUbTvUr+ivX+kosbYm360QRztxCT5PhP4RNtAp4WOazKH8hK/RaZQ8cB9l4t +Ecj1BoeUY9aV29J8uc9EDKeYTHbQ9tyAi5x/NIUfTw/uS7sMAuOfvRvb7eCiPxpU +N3/g3BSXGZUBzktiQNHTeK3TDmRY8V0t8RF/CtfOVx7mpsOtXv+d0hczkW0= +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/intermediate.key.pem b/fabric/etc/ca/intermediate/private/intermediate.key.pem new file mode 100644 index 000000000..b999d72aa --- /dev/null +++ b/fabric/etc/ca/intermediate/private/intermediate.key.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,6A6AAFAB303DE8A7AF0C9AFBC7298893 + +DQsdCbGQ7/Fuyv8BmCTr57eK1N08RC4U6udkYLKa9fEFISXr4uYwiKoHXJV10ViI +JWbll4wSip5xizdG2QhTQt9MqXbYYT16gZm5NeyrXzfZmw/9Jd87SxZD6XhKmJii +lokT6KTzjNDYUNgk2SN3SdIRn5wXFiNBEfkeaxW05q1DCTP+EKJrnsvMCcjZiTi2 +rnlMvz1SBw1lSZHjR25puXwl7oUgQrt4v7f2gv/QGjuAyW/vzY5biA2ug620Qe/P +6bqkhRVhW08QM7Xdjfaykdr7ZKfbRyi+arK0llJ0KT8V319w4kHyr4AQvTZcyBj2 +DRCjFuvp03cJ4O7CPK7fB+Bqm8EvbR3a0KJeGK5W9sCRKZXIFgRV1fQpdShZf0qP +sFdfDLj7OVbeERIpoRZlt5/qXc1gfIyxG7XJP+eUPmRCqriYo1x7+Y/jZ0yhHbYd +2qULvF5C1WhJbWxisbZYK4YMKSHMAX41hRn3oLlN8LotdVq6ivDM4E8KzJnKLDJx +xjZWmdKshGDIdqShkAPb36RdgUJV7+rLDSg2BdG2ZSyl5i7JpS1r9OlyOeo4clyA +R0/B0woqdU3E5OnPEQ4LNat1IBX5pSXjwDmiM8VwXpqB9YCrCizUbN8gAh6ihXrz +2TW536rBFfBBTIKYT5Qg3VsoOfHSx9ERlsR428YHTFweQISWhMyVRNpUCRsDVqll +9kFzZ9BFbNT/GkyUEvL45kGsbl9b4yEXWa+tcYzvtWtcRzY4RLIy9BkgJV26/Dzk +JgIVM3NngbDiqQo4wp1a74kGzFgNm+MWa+Br5wmWQizGPWxOCev2iN4FS6Mt9HAr +icS8rd/+B5OUSXCsnEveiM80gsPznukPtQGDoX3GLfOCf4GaNJLuNg65xiIHi8Bj +HljsSCPOENPbBIVREJScbHiF8c0w+8FinrBBW9FNJs1VuDgeD8bnk1BpAZnRoDit +q+1BayZIdL2xlwB39v6UFgPwiTG40HtMfuWa6DKE6SMAbZFrNQncTTAjjIDrJLiQ +I6DqQXYt1s355BhUW19cHfqGcXkaMH4x2hOjZSxlxb3PELMTkfGJ38V8FjrUn1XG +FReMP6kZoaiTmj4TwRlLdUuGaUDURdRhVMioh+FJyk2PFX1LQjID8IXHCiUBM3qz +TVqRDuyGpDZFi3PyAEEDOBu97qWpr6FYOODMZs2tPg2CuKjpdS0zrVpI9EH+gDBY +GLbSOwmLIjqYVjxPAXBZ0l1o/pWuPuRvYmUdzxmc4+XOnOJ/aQ9Hkw5Vrbf59rZr +wSv13Fcd0A+CIs/I0/u+U4RR8ffgFccVS15bqM2IWx5LlW9FneasZFztnTsVGcxv +uZEOhONC5usiVaGIuPYzhzSPT2h7hBSkoHWt+J48kRQuG7IoShVZTp23mo65UpTf +X0UZmcyTkoJcQ4yaRcX8trFjSjF2xhxnSMvjqgHHsLwOgchlOaIBxs16JnFEhmX/ +eeUDDOr13/y/ljbkwBq37tqhfvrxqUU8hqa1lu6z9Mocc8uh9RxC5Jq22NMAGb37 +5TzTGwRO1unTz8ke/RybVpm+Ft3swKbnscqVAgVXLkBtI8FIrdcOD8QX9HukpmRZ +eSWkO1fS2IISVFFqdQ7R9Wz421cnpMa0hdPB0cmXdrVz3E59OqKZAymDtczrJuxc +Ubd1H798a3bKzola7qt5TJBtQCdVEOuqskFC6aOGbsVu3j+MrwyBgyfthsFPdRn3 +Xn5ilxF8y1GTC0MOA6crBt6xka1Zb4uJOQUyuyPNqYl1wqF7Knki6fyTwa8xSQ6r +qxa727iglYdw+7D2rjydrX40EY3BAXTHnO9U8NEZKpvNeOiAoBxqGRfuGmwGjIay ++NcHLOwwnnUokN2/m9FcZ3iLYTNs+Ks3THPjTxHGUzfGe5vfBcyw9bcbocqBd6+i +T3WNsnaGMtDCsI7rLs7D8FlX4z0XYjP8UzqgyU/piWwC4+S3oRVcg0fRox1277FT +qIytjhID11GNPCmv/yhM5jLmQomKT87OEjP9XzbYqfyno9SzReJNh1bNiOW4AJhB +6qmlfEetdfRW0Spv0lA6l/V8OTQgyd6XWxQWzcjmbnNAJu7W5maPHg9K4tA9lhjl +DSvg7P1NZSOpW1tpjFOC81pYDG5ADwU652WTss0E3j0g6LAN9XWXa8hhzyf2OzYV +7cbGjFf5AY/iY8h05IUm6cJekLNS7gX3ipMqs3T7IpUeOZ93Qq0SlMKnIpSKBSH/ +kCpJ8GyFwyuxQ/6deqM2ucMvGKoQ7/wqvL33vWITqc84B45PHtuzaw9Xtr648c3B +U66HB26fwZCXNdYR7HOb8rwBprJ3e1iZMxHPH4m4aoHmUettTl0dXnDIyeNhKe23 +rWWN3hZyWlSZbAa2tSTzO03Yo1TKr0Yz/C+HFmy8zTMfsyLiuTAmZtLcRpAThc4u +lcKiL9R+mcf0V388sCeFcXXbm23pis5A0krtsS30wR3sFKujfadZICQOKULNHOes +dmW4EG9bhs6DTeII4g2bAEXYfX7mqzTUzuw/GCrZQPrMWOkocB+mNhHlBeV5l7RF +u/KqveO0h4dIBfruP5rP+fI2pHMgPMXX8UcK6/bGLgiLth1C9Z8pYjwT5gQHDcOy +oyJLzQrSI1ym8u8E0tXL5mamcOjnLhjQK+UfDaeKzF2mYpjYGu+BGYRabIzM8vKv ++nXG+SaEcCbQ8MXRVMDcj2m528WiU9des3QSgQwgAdq1JZZZopVUPjq1MWrgp/bt +OqZz2yjd/Rul672h1qi2/D7T/Yqf1s1ktsNv9z/1EQmA/pZrXrLbHfFo09RWqapB +AcazxdODYNTNhYxp7vppWci5fQj7j3luO9GV/m/aILe8mAkrnbkS2NHQFABVAgnZ +np8M/6wmBvhQpT6GJ1MHz6UBmXX+pTh+dprd2gSfDpcSUTjCzelsc/fNCKTQv0x+ +KZRzUWFOvSZEf2OM+dXjRydEskpIbcqtFKZkV9hlrHuhBeZwQCXuzxAIGOl1LKNF +7/0cbhr9fH/z/KVEY9+EyJ5nTHDnYSt77mmxlZVvKsPGiBz54G6tqvj+yonrQqZw +aeL+HgqHJRkV+13g+WeixwmPTX61Qu2rzUEYKGatjFvrlDQ0dB4SbYSjh/a5uYGe +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem b/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem new file mode 100644 index 000000000..e9b71c248 --- /dev/null +++ b/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAtJU/MT5Om7hLHOj+u8f+rBlzdx6xcQc399Fd6kLywH5m+jPc +6VWrM0r6B+rrTMvxud1XvrwFQ5RZrYXvGkMqWTWX5ZVQeXOe+UcBVhFKRx7F7V2m +RLQiwgCswzWBsN00pq6Wee104GX54mj9nrovb/V4kX1q1NJrR0rbEwIG8gceJGT5 +xt1bHsMpd2QXDqZG6s4oX4ib0QItxs2wNY+7YUuA996Je+6uihD/es2m4wkpjKb/ +snMEE1gResXAzGfLjBAxoCO7UlSC6wlrxnRsvTMYLWV9LuLLc5PmzF9crMIU5LSK +YIu6uNeWeuetco7QfZmyxsq74UNBlr5Z5tRRGQIDAQABAoIBAHBIADOxJxVhwKpo +IMNHdg0yAf5GAlRiBaW782YOXHvd3E+j4a7fioRpEQ/NPKLSiCll/AHnTGqZmizv +gxzUOEehsCGa9p+diXI7eRQ3yfRwqOaO/SvoyVfRLZpu8YWz9OHS2lNTlwFTxszF +NTT1VTuK6H2l+r/7WaLJY2/tKb5gLF8BYMUBrggMkWnsubwx4PHOT6Nbk5Br17Dm +BvP66LyiO+QPSv0bd3POf8ajq8prs4PSL0TvOeonQPoOBPg33iAZrfh++V8hTbLF +xLk0nacr5gr+1jZJ7yahb4N0oJ8iJbGLPW86lX3xTEbL+kduykLz+OIC7sh8Yowa +yOQ0/aUCgYEA6NNTAMyv+l3UnsSm8bU89PeirxbJOOOdUdZzmLtge/WU68anMcWZ +ykXbxDbk0NoJ46K/VEIqg05W0BCsbRM/XL6tE7hdd5sNh0E3ibC1kyGo270Q+l/t +rIt4FRPyKof60976fQ6cjoon08VaNXX2CzsSWi0r5SYY8NwfDA/AUhcCgYEAxo64 +ebaIQIh5h6XtoQfX+HJxTkO+2L2QVRbvBbeNMir3pVrcXg+p+F5HsRPaWKN70KgJ +STnGOgJIMfU4zTD2r9mewtkC4kUAzcoAYDQbJSXmNv4eFecjLIktsQ8g6J3MBGFz +HjXbt8Xt8sTHitmdurAyzJD6Iqg5EO2zu/0mZE8CgYEAsJ+oByJAmelWo/9BOnoo +PRojczoQ+rRJo0zRstrrDf62s8qnCa4Cxh0K5CZUnU/bUrIi/VOYlrX2S69qbvC8 +D6qi+CPT3ClnMOU7sZu5k11kkRYz7Ayb7Fp9hVf1TWiM0vAEDJzqDYQnRJMhpQ7Q +0aJFgN1lwFePciE6+FZ2qo8CgYEAjh+OUCClenu1cbEFXKQ+pKlWDQ1Ux9M4Qo+9 +2zu9J1G2HXfiELnpkcv6SPfK7HNoprwAmZdvGgqUHp5GYClSCiEdEJ9A/zEhGCwl +BLeHTpnIJUjTxB3EAZbXS8tmZNq+M8yFF/S5JtvYLFNJ+Us3KXABjIehY7lBz6o1 +YrQbDOUCgYEAsywWHGLGW0hhNb58ulDqWvnzSewjenrNF9JfpSXKd1L0LSu6NMdU +aRYjk2En/HCGWHXrwInntzkq+M164hHU6oqPl9TTyBepc4qgD/QXbqyDUaAJcEVe +dXDLfCTt4ApDaunaICEplWXba2hOD1YySJREXp5wtswzUKWT38KXWdU= +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/intermediate/serial b/fabric/etc/ca/intermediate/serial new file mode 100644 index 000000000..9951021cf --- /dev/null +++ b/fabric/etc/ca/intermediate/serial @@ -0,0 +1 @@ +1013 diff --git a/fabric/etc/ca/intermediate/serial.old b/fabric/etc/ca/intermediate/serial.old new file mode 100644 index 000000000..2d1420d53 --- /dev/null +++ b/fabric/etc/ca/intermediate/serial.old @@ -0,0 +1 @@ +1012 diff --git a/fabric/etc/ca/newcerts/1000.pem b/fabric/etc/ca/newcerts/1000.pem new file mode 100644 index 000000000..635c498e9 --- /dev/null +++ b/fabric/etc/ca/newcerts/1000.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGBjCCA+6gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNVBAYTAlVT +MRcwFQYDVQQIDA5Ob3J0aCBDYXJvbGluYTESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw +EQYDVQQKDApOZXRGb3VuZHJ5MSkwJwYDVQQLDCBOZXRGb3VuZHJ5IENlcnRpZmlj +YXRlIEF1dGhvcml0eTEbMBkGA1UEAwwSTmV0Rm91bmRyeSBSb290IENBMB4XDTE4 +MDUxODE2NTcyM1oXDTI4MDUxNTE2NTcyM1owgYsxCzAJBgNVBAYTAlVTMRcwFQYD +VQQIDA5Ob3J0aCBDYXJvbGluYTETMBEGA1UECgwKTmV0Rm91bmRyeTEpMCcGA1UE +CwwgTmV0Rm91bmRyeSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIzAhBgNVBAMMGk5l +dEZvdW5kcnkgSW50ZXJtZWRpYXRlIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAsb1EPhMUweS9WpjT7L54xAOmZqugJ6fhSrFfLUwNUy172q+ASvZT +pT1zKIPcZpGmPB3TX2bHaAR67BbRkUR11JgWE3U8+FsGrYmPZtaKM6fg8Mh0WZ41 +oMYQNJyQixOktrgqfybyJoT5PeT5AA7QQmd8mku2X9nkAu6gWPf2nHNc7SeQdijm +yQQaVK3oqyaxOzWzsU/XbfMEz/ObkefUxgt5Z6jlK0xcW0Q+QgtawMKLUiuo6obW +RPcl7Hm9Sze8XJS5pbvS5JkUszxoRZuDVHZylrlHIpA/IL+BnvS+M7SP28UWe9sk +rv/s6ACpJtuPJ1EYf5fakugOpY7i+hq7YNi//csbc49Qjn2OtttrR7JcTaHUEU1I +/tQbQGAtNkI4pJjRVUdDawQFQlWHZD1COixNLErs2HzAI00DhLrY6SKITI/kjN0X +x010XdMcdfay0PLWm6RwxiRmMQFL4GNIC895NF1q6xV4W4rWgqUNlcvKpy+i1chW +pRbUHe16ul0qh10fcESrRvAbXn5YrQJLrwbSr+85ubN8lYdNLE0qg2cIXZlUilar +ZZzWghtCe+KkUpjfRuAi/CqfSwNK3QXEfeVEK6S49mHeSekOizFIw7fmDhCz9vXw +MOnbryRSLEJks0gIRcSDVChXheAqC98y4kcQdniNWFnqJXoqA+rrSokCAwEAAaNm +MGQwHQYDVR0OBBYEFK8UXC/sq6dGVFAqEXHsQDzqzwuUMB8GA1UdIwQYMBaAFEHz +6RRuOuXj2mwAzOeUinfWeivpMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBDAAaOE2Nbb49eOjyTNxIeOB+ZKQjJ +1hUEgRrootAA8NYbtKW/vyxTWnNi5XOGXd4DFS9OKZ0mL/7NyLc0mbTwPH2ZT8KT +PUTSCpo6yktZ/7TMjyAtWZiOMg2EH+6m/nlNSXk/v5fb8+JQLdZfpxoA017dHh3t +c8l7KOskCZNwQHgF/YMXrPXUNbsGkXRuJLtpjPw5O9GvPys7p+a1aJH1WCTly9zf +B6j+rMF+UGCPDT30sxitVlohik83j6pKLgEAP/gi8nJbILlTP7ce+gJeHR2tfDvm +K91X6QgCF2STUFBU7/9H1/pPRRykOxQpAd8xqSgqGEyp9Ie4tysZjwoUEnG8IVJ5 +ykrIFximvnb4B+LABV9WEo08n8m1R8wEryrISi8fBPn3Pr5nuayOfFLa15CLTkZF +40FN8ika1qNZy8bWRDwTZJQUUb7VCheRWcMwdZdNmhl3J+VZLpQ+ruW7b2ajwacH +z5NwBHKNcmxXb/4vHq/BnlcayHnSqT6036+OZQ+owDegcYmWV6LaM7xLErjHz2EE +38M2YSiW5SU1zluDe+iHb6l3Gd3Fj/X1gkMWFgYh0XPMSUSyimLNYzy4THKzmWlc +QNFoLLiIDbLrMt+vk+vBkIsNTTPXRJOFPBhmIF6uIUj+2YhzNotX/pQtqMKms3pP +lmHqdH6biwygEQ== +-----END CERTIFICATE----- diff --git a/fabric/etc/ca/openssl.cnf b/fabric/etc/ca/openssl.cnf new file mode 100644 index 000000000..f85e840c7 --- /dev/null +++ b/fabric/etc/ca/openssl.cnf @@ -0,0 +1,131 @@ +# OpenSSL root CA configuration file. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = . +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/ca.key.pem +certificate = $dir/certs/ca.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = US +stateOrProvinceName_default = North Carolina +localityName_default = Charlotte +0.organizationName_default = Example +organizationalUnitName_default = Example Certificate Authority +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/fabric/etc/ca/private/ca.key.pem b/fabric/etc/ca/private/ca.key.pem new file mode 100644 index 000000000..63ed44317 --- /dev/null +++ b/fabric/etc/ca/private/ca.key.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,1A3811FB90FF608B99A64B7C79FDD36A + +DB6tCN9qvMEbWJ2jeGw0I8PybGMQdCfkVF7QrUofNlrm3hLtl5gdk+xSOSE3zMw4 +aMdjmDfACscNx9Cfl03pcn3ZewxQY+p2iznT0KoWFxMdTOxjZC8m28t//IRn323L +8eiIcsx7oc+MVCeUG1UICAnU9vEcDDc2kTm7A4uMOQQ6EgO5/1kWgxJLxS75/wmE +mPHSbbBh8Iso95ygrDZKxRSpBY7i78NBtSFL5AHXxpGStravgHbH0aBNPQ7zoJ85 +0oZtqAPDdTPouigEV4O9Cfrneq/xaLkVB3NiZBo9m7ftVma/81lRYKiuWhGU56Va +ESqHvt3QWNV3ZfITALrRlZNpPP8gxoKfv/kvtyPHQmNvx48oXzAcAKA5rLcDjQcf +weiEYiz4GocyKBt2mrqEQ5rReVgfgMEK83fhsEDS5xpj+KwZJyx5rUE+s+yRGLkq +pO76cuFoKPQ+snX9RkUYSQe+cemD4CoMRbi04OM8jUypB4+wyzNf1mnM7q7ozwow +O0dVGdETQ9SGEAg/Rg37JsD0+PVzwwpDDv66y0GYBWgD7trJ6x2nydhrOMjiu8PV +3XWRX+zpLNwKobTWPYtdHyVG4T2q+JC+0yHr3pp2TV/+wTumHcsmzwi/D+o8RWwe +oCj2Oe17X1bsdL8hve5H4h0JPA7zYEArBX76JUaeu2iyWW7lVnXRpO5iyEuoIw9P +hQ7larLVBQiPuiNinit9MQX3svo1VcCE51WHz+1ORBt1edMCeCocEZXZ3xRgfRQb +Q/dlOXxnY88r8Rf1iPo3NxqSkRv3bw+R7BuQwmr0852xU7JnfzLW7IYIEVwAMWf2 +Uummlj7LJ5xfmV1RMlcwrQuilFqGvBQYvF5eMkZwqJgj2D7iDq9S0mUytPhqyEZj +qWBjKK+PK4yZyzyIreGD3s92DMi/CEt0qkig84ZR04Epe61qD1C5fG5LSVA+hNnd +uT1pNiesgZBfkh5YKtqFM/E4SJjjEwP7lTzl1eCJybw+LNJITzffg+E5hsKjE8X6 +ZqLVBkmBi7YaIoZ3LVcv6fx3pMk5GxZqaRI0vLv+kI1kFzl3/Coy/nVOSj7MZ6E+ +VKzDTSsUSCPJE+MtIAdsTgh+ukBxDXiVQEdr+sd+wX8JhOWJNgIZBlTNDM50rtgK +6OiD3dwy7p0z+ZvUeGWsMCK94uXccZjHfqta6A9WBpW6WSamb9UBY53ASkSyRgdu +HFlqTeCb4T1Zu9UcZfKiqma76Ulta2K4tmke7g91/gfR1wujZ5AZ0VRS5WJsubyZ +J2LloKQwrKY5DJiNSD9vECKRDyW17fLWMhKtmJ2IPFa8ojJEZkMg0coOXndf/+ZG +r3MzW9QYrLcuVyZH9pwSve0n5XeLYZTZEDe+qikcBseQpoZbdv0fRrh3mZ1BN0Ha +5R3z+rZDKAQr38VXbEuPO+3Vuz18q+UrxwqUpX13Manc2Lwv/JC7KDJm1rMPLbID +ZZnKaph6ut6ExSmOK9Vv+TUk5Sfb0juuD+ugUSJsUd0vnIymbTDcBCKeKXyZPtCr +fRfHoeqfEaRNjtXbfdyGIa0UGq+iaCyiIdjJpoRx23MVjNS51CFm8ZGAiz92iSVT +ha1IsRiopB9uLTFnPqu26fbyaccppcDP5mvr+Ig/x5ka1GrR3Ys/8e5FB9S2CDFE +VB83G7085UBZbwH/X7fdQ6v0OUF4b21bQDrXkWqIWJptbyxfc6QO+7C3BDFqPQNT +40T5ORbzBUcovMmnkrnqKXylEKkBhrOtp1U1sf+5/oO9MUQsgSrv7zfcf9375HUO +sAQrL+oIntHmrSVyP6nl5/VyIoyzFwjRPh7602dbzbxclTrH5sOw1+YZE8i313cK +/XZ5/q2YeorypZWh2+tWqhOq4jvb/uXvrhtmxu1plQucXy6We0A7ohr9ExVajh9E +iOb45z/kO2Ub/iuYKuvjwKmSgT1tkoF57XbbQte9BD/kc+cMfxmYrPa27HzS4loY +uFnOBchqaZxav9NBVcgpfanj1q/7rQa+CtncA27D5N73xP4jYq4UXDCqa9YPSQj/ +9bLKXthMiU2sX5jMuR0dO85yv1PcG061sIdvHUyOqcINiKWpBAabk59bikwZ6Qvs +yznBHaD128JPP9VheHcnug6fCqFzze6WOJAXE3/Meib78qzZY+G4KXvPjpBa6tuT +UucbJ2WvLwGbBr5UnNc5PBk7NoVxiZz9C/IPQxQ6D/PnjFfR7xsD8t4aFwBYZtmP +wX1K9rfspIcQONzfLxahmOTi7oDVhJKlu/3fVLpKMqEWpYLydtfx+2QfpzKDEgRE +SihBYlk5bH6sV57qRfuz8omJc/pRVsg2y4u6eU2ku9oPUbTvh8cqoZ2FPaXSVHyR +EpK8t0QexKJ/Sul0I0qjNFwJZqYfT/mLt8+qZ7CDGBG8MHTX58Phn3rHa+cSaZJv +PGBkeLeUaoLSGxqnEF4roRhaCQOKTwVNMsRerMJgqI1tx1llQ04VDJhHL4AYKf6s +pi10lmpVTqe73ou2fykmXhgRW6SqeljbJq8PNQKlRAit9EYRxmbXjU/eWRAI6maM +EE6ArcxNGnWpaDA3M6oo4Z+8wzLcpuCRBtNil0aMRGpFq6sPVOsIZKyv906Ylko2 +g6Sh7iMySCMzOdqFmmu4E6IwJoId4TleAdtu+JOJt5nFv+X+2ioFQgMnOVpGdGdv +4SIRQARdfHQqJgrkZTu/vMbq/6mcRo+cuec64eyXfiLxCl1xV7f8m0JL7CA8Nva8 +TBbQNIDL9lCw5zHk2OhYhx4tfQrB0Igt9cxiMg11jUwMqALBIbu7C0PX2QOnj6pG +3sGV5mGdPk9mGQ3+F2ZQ/DnBK1zH2fT+6AGqSac0qv16fJqbUxzRqnVq5vT7RwSP +Gm5O2qDjYa4boMbMwfNe5Xiet7NYjdJ0nLbkQOxD3+mMiJtYH7XdSOtczajm+ftc +7K/D7yxHgqDr1ZaPFmgBVOp6PSUIIg0Nc9OH+tx68wK8HkJafA7Kvh6PJILjLisC +UKL1X4pQOZG02VHcoTpFOUiR8iG+nFRt1cWM4BZ/QkUIUmw27hLO8Jx89osgFl93 +Z+diGoRLwR9AUD81geRUguTOGaH0ugFbVjniF9IhFxP1n1yuvwjyMQHdG1ext+Dm +-----END RSA PRIVATE KEY----- diff --git a/fabric/etc/ca/serial b/fabric/etc/ca/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/fabric/etc/ca/serial @@ -0,0 +1 @@ +1001 diff --git a/fabric/etc/ca/serial.old b/fabric/etc/ca/serial.old new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/fabric/etc/ca/serial.old @@ -0,0 +1 @@ +1000 diff --git a/fabric/etc/ctrl.with.edge.yml b/fabric/etc/ctrl.with.edge.yml new file mode 100644 index 000000000..44291cd89 --- /dev/null +++ b/fabric/etc/ctrl.with.edge.yml @@ -0,0 +1,79 @@ +v: 3 + +#trace: +# path: ctrl.trace + +#profile: +# memory: +# path: ctrl.memprof + +db: ${ZITI_DATA}db/ctrl.db + +identity: + cert: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem + server_cert: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem + key: ${ZITI_SOURCE}fabric/etc/ca/intermediate/private/ctrl.key.pem + ca: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +# the endpoint that routers will connect to the controller over. +ctrl: + listener: tls:127.0.0.1:6262 + +# the endpoint that management tools connect to the controller over. +mgmt: + listener: tls:127.0.0.1:10000 + +#metrics: +# influxdb: +# url: http://localhost:8086 +# database: ziti + +# xctrl_example +# +#example: +# enabled: false +# delay: 5 + +# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the edge to not run. +edge: + # This section represents the configuration of the Edge API that is served over HTTPS + api: + # (required) The interface and port that the Edge API should be served on. + listener: 127.0.0.1:1280 + # (required) The host/port combination that is reported as publicly accessible for the Edge API + advertise: localhost:1280 + # (optional, defaults to 10) The number of minutes before an Edge API session will timeout. Timeouts are reset by + # API requests and connections that are maintained to Edge Routers + sessionTimeoutMinutes: 30 + #(optional, defaults to the root identity) An alternate "identity" to use for the Edge API. If this section is not + # defined the root identity section will be used. This is useful for situations where Edge API will present a + # publicly signed certificate instead of one generated by a private PKI created by ziti pki create +# identity: +# server_cert: edge/tests/pki/ziti-dev-controller01.external.cert.pem +# server_key: edge/tests/pki/ziti-dev-controller01.external.key.pem +# ca: edge/tests/pki/ziti-dev-controller01.external.chain.cert.pem + # This section is used to define option that are used during enrollment of Edge Routers, Ziti Edge Identities. + enrollment: + # (required) A Ziti Identity configuration section that specifically makes use of the cert and key fields to define + # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert + # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller. + signingCert: + cert: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/intermediate.cert.pem + key: ${ZITI_SOURCE}fabric/etc/ca/intermediate/private/intermediate.key.decrypted.pem + edgeIdentity: + # (optional, defaults to 5) The length of time that a Ziti Edge Identity enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + durationMinutes: 5 + edgeRouter: + # (optional, defaults to 5) The length of time that a Ziti Edge Router enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + durationMinutes: 5 + persistence: + # See documentation: + # - https://godoc.org/github.com/lib/pq + # - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING + # (required) A Postgres connection string used to connect to a database + connectionUrl: postgres://postgres:ztpassword@localhost/postgres?sslmode=disable + # (required) The Postgres database name to use + dbName: postgres diff --git a/fabric/etc/ctrl.yml b/fabric/etc/ctrl.yml new file mode 100644 index 000000000..8f93756aa --- /dev/null +++ b/fabric/etc/ctrl.yml @@ -0,0 +1,40 @@ +v: 3 + + +#trace: +# path: ctrl.trace + +#profile: +# memory: +# path: ctrl.memprof + +db: /tmp/devctrl.db + +identity: + cert: fabric/etc/ca/intermediate/certs/ctrl-client.cert.pem + server_cert: fabric/etc/ca/intermediate/certs/ctrl-server.cert.pem + key: fabric/etc/ca/intermediate/private/ctrl.key.pem + ca: fabric/etc/ca/intermediate/certs/ca-chain.cert.pem + +#network: +# cycleSeconds: 15 +# smart: +# rerouteFraction: 0.02 +# rerouteCap: 4 + +ctrl: + listener: tls:127.0.0.1:6262 + +mgmt: + listener: tls:127.0.0.1:10000 + +#metrics: +# influxdb: +# url: http://localhost:8086 +# database: ziti + +# xctrl_example +# +#example: +# delay: 5 + diff --git a/fabric/etc/edge.router.yml b/fabric/etc/edge.router.yml new file mode 100644 index 000000000..b0628d92b --- /dev/null +++ b/fabric/etc/edge.router.yml @@ -0,0 +1,83 @@ +v: 2 + +# (required) The certificates, ca chains, and private key used to represent this routers identity +# +# If the 'edge" section is enabled and enrollment is run, the files in this section will be written to with the results. +# The "key" value can be provided through any of the support private key engines (file, etc.). +# +# If the 'key' value is a file and that file exists; it is expected to a pre-generated private key. It will be used for +# the enrollment process and it will back the certificates generated during enrollment. If the file does not exist, it +# will be generated. +# +# The 'cert', 'server_cert', and 'ca' files will be overwritten with the results of the enrollment process. +# +# When running the ziti-router the files/values in this section will be read and used. The 'cert' value will be used +# as the client certificate to connect to the controller. The 'server_cert' is used for all servers/listeners. The +# 'ca' value is used to populate an internally Trusted CA pool. +identity: + cert: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ignore.gw001-client.cert.pem + server_cert: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ignore.gw001-server.cert.pem + key: ${ZITI_SOURCE}fabric/etc/ca/intermediate/private/ignore.gw001.key.pem + ca: ${ZITI_SOURCE}fabric/etc/ca/intermediate/certs/ignore.gw001-ca-chain.cert.pem + +#trace: +# path: 001.trace + +#profile: +# memory: +# path: 001.memprof +# cpu: +# path: 001.cpuprof + +ctrl: + endpoint: tls:127.0.0.1:6262 + +# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + dns: + - "localhost" + - "test-network" + - "test-network.localhost" + - "ziti-dev-ingress01" + email: + - "admin@example.com" + ip: + - "127.0.0.1" + uri: + - "ziti://ziti-dev-gateway01/made/up/example" + + # (optional) Configuration specific to the controller's API that is proxied through this process. If not defined + # the API Proxy will not run. + apiProxy: + # (required) The interface and port that the Edge API should be served on. + listener: 0.0.0.0:1080 + # (required) The hostname and port combination to the ziti-controller hosted Edge API + upstream: 127.0.0.1:1280 + +dialers: + - binding: udp + - binding: transport + +listeners: + - binding: edge + address: tls:0.0.0.0:3022 + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: 127.0.0.1:3022 + - binding: transport + address: tls:0.0.0.0:7099 + diff --git a/fabric/etc/gw.yml b/fabric/etc/gw.yml new file mode 100644 index 000000000..e1ce85038 --- /dev/null +++ b/fabric/etc/gw.yml @@ -0,0 +1,10 @@ +listenAddress: localhost:10080 + +# Comment out the following lines to disable the TLS listener +certPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem +keyPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem + +mgmt: tls:127.0.0.1:10000 +mgmtCertPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/mgmt-gw.cert.pem +mgmtKeyPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/private/mgmt-gw.key.pem +mgmtCaCertPath: src/github.com/netfoundry/ziti-fabric/fabric/etc/ca/intermediate/certs/ca-chain.cert.pem \ No newline at end of file diff --git a/fabric/etc/loop2/10-ambient.loop2.yml b/fabric/etc/loop2/10-ambient.loop2.yml new file mode 100644 index 000000000..657647a90 --- /dev/null +++ b/fabric/etc/loop2/10-ambient.loop2.yml @@ -0,0 +1,30 @@ +# This is an example workloads definition for the loop2 tool. +# +workloads: + - name: chatter + concurrency: 10 + dialer: + txRequests: 2000000 + txPacing: 5000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + listener: + txRequests: 2000000 + txPacing: 5000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + + - name: big + concurrency: 1 + dialer: + txRequests: 20000 + txPacing: 10000 + txMaxJitter: 2500 + payloadMinBytes: 51200000 + payloadMaxBytes: 102400000 + listener: + rxTimeout: 30000 diff --git a/fabric/etc/loop2/1k-stress.loop2.yml b/fabric/etc/loop2/1k-stress.loop2.yml new file mode 100644 index 000000000..1eec4a1a3 --- /dev/null +++ b/fabric/etc/loop2/1k-stress.loop2.yml @@ -0,0 +1,30 @@ +# This is an example workloads definition for the loop2 tool. +# +workloads: + - name: chatter + concurrency: 1000 + dialer: + txRequests: 2000000 + txPacing: 1000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + listener: + txRequests: 2000000 + txPacing: 1000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + + - name: big + concurrency: 3 + dialer: + txRequests: 2000 + txPacing: 1000 + txMaxJitter: 2500 + payloadMinBytes: 51200000 + payloadMaxBytes: 102400000 + listener: + rxTimeout: 30000 diff --git a/fabric/etc/loop2/256-medium.loop2.yml b/fabric/etc/loop2/256-medium.loop2.yml new file mode 100644 index 000000000..8f036b27a --- /dev/null +++ b/fabric/etc/loop2/256-medium.loop2.yml @@ -0,0 +1,30 @@ +# This is an example workloads definition for the loop2 tool. +# +workloads: + - name: chatter + concurrency: 256 + dialer: + txRequests: 2000000 + txPacing: 1000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + listener: + txRequests: 2000000 + txPacing: 1000 + txMaxJitter: 5000 + rxTimeout: 15000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + + - name: big + concurrency: 3 + dialer: + txRequests: 2000 + txPacing: 1000 + txMaxJitter: 2500 + payloadMinBytes: 51200000 + payloadMaxBytes: 102400000 + listener: + rxTimeout: 30000 diff --git a/fabric/etc/loop2/8k-chatter.loop2.yml b/fabric/etc/loop2/8k-chatter.loop2.yml new file mode 100644 index 000000000..1d564a90e --- /dev/null +++ b/fabric/etc/loop2/8k-chatter.loop2.yml @@ -0,0 +1,17 @@ +workloads: + - name: chatter + concurrency: 8192 + dialer: + txRequests: 2000000 + txPacing: 30000 + txMaxJitter: 5000 + rxTimeout: 240000 + payloadMinBytes: 128 + payloadMaxBytes: 512 + listener: + txRequests: 2000000 + txPacing: 30000 + txMaxJitter: 5000 + rxTimeout: 240000 + payloadMinBytes: 128 + payloadMaxBytes: 512 \ No newline at end of file diff --git a/fabric/etc/loop2/example.loop2.yml b/fabric/etc/loop2/example.loop2.yml new file mode 100644 index 000000000..f139f2a97 --- /dev/null +++ b/fabric/etc/loop2/example.loop2.yml @@ -0,0 +1,30 @@ +# This is an example workloads definition for the loop2 tool. +# +workloads: + - name: chatter + concurrency: 10 + dialer: + txRequests: 20 + txPacing: 20 + txMaxJitter: 100 + rxTimeout: 5000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + listener: + txRequests: 20 + txPacing: 20 + txMaxJitter: 100 + rxTimeout: 5000 + payloadMinBytes: 4096 + payloadMaxBytes: 40960 + + - name: big + concurrency: 2 + dialer: + txRequests: 1 + txPacing: 1000 + txMaxJitter: 10000 + payloadMinBytes: 51200000 + payloadMaxBytes: 102400000 + listener: + rxTimeout: 30000 diff --git a/fabric/etc/loop2/failover.loop2.yml b/fabric/etc/loop2/failover.loop2.yml new file mode 100644 index 000000000..766c6c0c1 --- /dev/null +++ b/fabric/etc/loop2/failover.loop2.yml @@ -0,0 +1,16 @@ +# +# Workloads used for debugging active failover. +# + +workloads: + - name: failover + concurrency: 1 + dialer: + txRequests: 20000 + txPacing: 1000 + rxTimeout: 5000 + payloadMinBytes: 4096 + payloadMaxBytes: 8192 + listener: + txRequests: 0 + rxTimeout: 5000 diff --git a/fabric/metrics/channel_reporter.go b/fabric/metrics/channel_reporter.go new file mode 100644 index 000000000..7617a6136 --- /dev/null +++ b/fabric/metrics/channel_reporter.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type channelReporter struct { + ch channel2.Channel +} + +func (reporter *channelReporter) AcceptMetrics(message *ctrl_pb.MetricsMessage) { + log := pfxlog.Logger() + + bytes, err := proto.Marshal(message) + if err != nil { + log.Errorf("Failed to encode metrics message: %v", err) + return + } + + chMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_MetricsType), bytes) + + err = reporter.ch.Send(chMsg) + if err != nil { + log.Errorf("Failed to send metrics message: %v", err) + } else { + log.Debug("Reported metrics to fabric controller") + } +} + +// NewChannelReporter creates a metrics handler which sends metrics messages out on the given channel +func NewChannelReporter(ch channel2.Channel) Handler { + return &channelReporter{ + ch: ch, + } +} \ No newline at end of file diff --git a/fabric/metrics/config.go b/fabric/metrics/config.go new file mode 100644 index 000000000..829905a2e --- /dev/null +++ b/fabric/metrics/config.go @@ -0,0 +1,53 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "errors" + "fmt" + "github.com/michaelquigley/pfxlog" +) + +type Config struct { + handlers map[Handler]Handler +} + +func LoadConfig(srcmap map[interface{}]interface{}) (*Config, error) { + cfg := &Config{handlers: make(map[Handler]Handler)} + + for k, v := range srcmap { + if name, ok := k.(string); ok { + switch name { + case string(HandlerTypeInfluxDB): + if submap, ok := v.(map[interface{}]interface{}); ok { + if influxCfg, err := LoadInfluxConfig(submap); err == nil { + if influxHandler, err := NewInfluxDBMetricsHandler(influxCfg); err == nil { + cfg.handlers[influxHandler] = influxHandler + pfxlog.Logger().Infof("added influx handler") + } else { + return nil, fmt.Errorf("error creating influx handler (%s)", err) + } + } + } else { + return nil, errors.New("invalid influx stanza") + } + } + } + } + + return cfg, nil +} \ No newline at end of file diff --git a/fabric/metrics/event_controller.go b/fabric/metrics/event_controller.go new file mode 100644 index 000000000..784526e73 --- /dev/null +++ b/fabric/metrics/event_controller.go @@ -0,0 +1,126 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/michaelquigley/pfxlog" +) + +// HandlerType is used define known handler types +type HandlerType string + +const ( + // HandlerTypeInfluxDB represents the HandlerTypeInfluxDB reporter + HandlerTypeInfluxDB HandlerType = "influxdb" +) + +// Handler represents a sink for metric events +type Handler interface { + // AcceptMetrics is called when new metrics become available + AcceptMetrics(message *ctrl_pb.MetricsMessage) +} + +// EventController allows for sending metrics to multiple Handlers +type EventController interface { + Handler + + // AddHandler adds the given arbitrary handler to the event controller + AddHandler(handler Handler) + + // RemoveHandler removes the given handler from the event controller + RemoveHandler(handler Handler) + + // Shutdown stops the event controller + Shutdown() +} + +// NewEventController creates a new EventController instance +func NewEventController(cfg *Config) EventController { + eventController := &eventControllerImpl{ + changeChan: make(chan eventControllerChange, 1), + metricChan: make(chan *ctrl_pb.MetricsMessage, 25), + } + + if cfg != nil && cfg.handlers != nil { + eventController.handlers = cfg.handlers + } else { + eventController.handlers = make(map[Handler]Handler) + } + + go eventController.run() + return eventController +} + +type eventControllerImpl struct { + changeChan chan eventControllerChange + metricChan chan *ctrl_pb.MetricsMessage + handlers map[Handler]Handler +} + +func (eventController *eventControllerImpl) AcceptMetrics(message *ctrl_pb.MetricsMessage) { + eventController.metricChan <- message +} + +func (eventController *eventControllerImpl) AddHandler(handler Handler) { + eventController.changeChan <- eventControllerChange{handler, addHandler} +} + +func (eventController *eventControllerImpl) RemoveHandler(handler Handler) { + eventController.changeChan <- eventControllerChange{handler, removeHandler} +} + +func (eventController *eventControllerImpl) Shutdown() { + eventController.changeChan <- eventControllerChange{nil, shutdownEventController} +} + +func (eventController *eventControllerImpl) run() { + log := pfxlog.Logger() + log.Info("started") + defer log.Errorf("exited") + + running := true + for running { + select { + case change := <-eventController.changeChan: + if addHandler == change.changeType { + eventController.handlers[change.handler] = change.handler + } else if removeHandler == change.changeType { + delete(eventController.handlers, change.handler) + } else if shutdownEventController == change.changeType { + running = false + } + case msg := <-eventController.metricChan: + for _, handler := range eventController.handlers { + go handler.AcceptMetrics(msg) + } + } + } +} + +type eventControllerChangeType uint8 + +const ( + addHandler = iota + removeHandler + shutdownEventController +) + +type eventControllerChange struct { + handler Handler + changeType eventControllerChangeType +} diff --git a/fabric/metrics/histogram.go b/fabric/metrics/histogram.go new file mode 100644 index 000000000..33674e3b5 --- /dev/null +++ b/fabric/metrics/histogram.go @@ -0,0 +1,35 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import "github.com/rcrowley/go-metrics" + +// Histogram represents a metric which is measuring the distribution of values for some measurement +type Histogram interface { + Metric + Clear() + Update(int64) +} + +type histogramImpl struct { + metrics.Histogram + dispose func() +} + +func (histogram *histogramImpl) Dispose() { + histogram.dispose() +} diff --git a/fabric/metrics/influxdb_reporter.go b/fabric/metrics/influxdb_reporter.go new file mode 100644 index 000000000..11d14c0d2 --- /dev/null +++ b/fabric/metrics/influxdb_reporter.go @@ -0,0 +1,232 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "errors" + "fmt" + "github.com/golang/protobuf/ptypes" + influxdb "github.com/influxdata/influxdb1-client" + "github.com/michaelquigley/pfxlog" + "net/url" + "time" +) + +type influxReporter struct { + url url.URL + database string + username string + password string + metricsChan chan *ctrl_pb.MetricsMessage + + client *influxdb.Client +} + +func (reporter *influxReporter) AcceptMetrics(message *ctrl_pb.MetricsMessage) { + reporter.metricsChan <- message +} + +// NewInfluxDBMetricsHandler creates a new HandlerTypeInfluxDB metrics ChannelReporter +func NewInfluxDBMetricsHandler(cfg *influxConfig) (Handler, error) { + rep := &influxReporter{ + url: cfg.url, + database: cfg.database, + username: cfg.username, + password: cfg.password, + metricsChan: make(chan *ctrl_pb.MetricsMessage, 10), + } + + if err := rep.makeClient(); err != nil { + return nil, fmt.Errorf("unable to make HandlerTypeInfluxDB influxdb. err=%v", err) + } + + go rep.run() + return rep, nil +} + +func (reporter *influxReporter) makeClient() (err error) { + reporter.client, err = influxdb.NewClient(influxdb.Config{ + URL: reporter.url, + Username: reporter.username, + Password: reporter.password, + }) + + return +} + +func (reporter *influxReporter) run() { + log := pfxlog.Logger() + log.Info("started") + defer log.Warn("exited") + + pingTicker := time.Tick(time.Second * 5) + + for { + select { + case msg := <-reporter.metricsChan: + if err := reporter.send(msg); err != nil { + log.Printf("unable to send metrics to HandlerTypeInfluxDB. err=%v", err) + } + case <-pingTicker: + _, _, err := reporter.client.Ping() + if err != nil { + log.Printf("got error while sending a ping to HandlerTypeInfluxDB, trying to recreate influxdb. err=%v", err) + + if err = reporter.makeClient(); err != nil { + log.Printf("unable to make HandlerTypeInfluxDB influxdb. err=%v", err) + } + } + } + } +} + +func (reporter *influxReporter) send(msg *ctrl_pb.MetricsMessage) error { + var pts []influxdb.Point + + now, err := ptypes.Timestamp(msg.Timestamp) + + if err != nil { + return err + } + + tags := make(map[string]string) + for k, v := range msg.Tags { + tags[k] = v + } + tags["source"] = msg.SourceId + + for name, val := range msg.IntValues { + pts = append(pts, influxdb.Point{ + Measurement: name, + Tags: tags, + Fields: map[string]interface{}{ + "value": val, + }, + Time: now, + }) + } + + for name, val := range msg.FloatValues { + pts = append(pts, influxdb.Point{ + Measurement: name, + Tags: tags, + Fields: map[string]interface{}{ + "value": val, + }, + Time: now, + }) + } + + for name, val := range msg.Histograms { + pts = append(pts, influxdb.Point{ + Measurement: name, + Tags: tags, + Fields: map[string]interface{}{ + "count": val.Count, + "max": val.Max, + "mean": val.Mean, + "min": val.Min, + "stddev": val.StdDev, + "variance": val.Variance, + "p50": val.P50, + "p75": val.P75, + "p95": val.P95, + "p99": val.P99, + "p999": val.P999, + "p9999": val.P9999, + }, + Time: now, + }) + } + + for name, val := range msg.Meters { + pts = append(pts, influxdb.Point{ + Measurement: name, + Tags: tags, + Fields: map[string]interface{}{ + "count": val.Count, + "m1": val.M1Rate, + "m5": val.M5Rate, + "m15": val.M15Rate, + "mean": val.MeanRate, + }, + Time: now, + }) + } + + bps := influxdb.BatchPoints{ + Points: pts, + Database: reporter.database, + } + + _, err = reporter.client.Write(bps) + return err +} + +type influxConfig struct { + url url.URL + database string + username string + password string +} + +func LoadInfluxConfig(src map[interface{}]interface{}) (*influxConfig, error) { + cfg := &influxConfig{} + + if value, found := src["url"]; found { + if urlSrc, ok := value.(string); ok { + if url, err := url.Parse(urlSrc); err == nil { + cfg.url = *url + } else { + return nil, fmt.Errorf("cannot parse influx 'url' value (%s)", err) + } + } else { + return nil, errors.New("invalid influx 'url' value") + } + } else { + return nil, errors.New("missing influx 'url' config") + } + + if value, found := src["database"]; found { + if database, ok := value.(string); ok { + cfg.database = database + } else { + return nil, errors.New("invalid influx 'database' value") + } + } else { + return nil, errors.New("missing influx 'database' config") + } + + if value, found := src["username"]; found { + if username, ok := value.(string); ok { + cfg.username = username + } else { + return nil, errors.New("invalid influx 'username' value") + } + } + + if value, found := src["password"]; found { + if password, ok := value.(string); ok { + cfg.password = password + } else { + return nil, errors.New("invalid influx 'password' value") + } + } + + return cfg, nil +} diff --git a/fabric/metrics/interval_counter.go b/fabric/metrics/interval_counter.go new file mode 100644 index 000000000..cf99c1162 --- /dev/null +++ b/fabric/metrics/interval_counter.go @@ -0,0 +1,178 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "fmt" + "github.com/michaelquigley/pfxlog" + "reflect" + "time" +) + +// IntervalCounter allows tracking counters which are bucketized by some interval +type IntervalCounter interface { + Metric + Update(intervalId string, time time.Time, value uint64) +} + +type intervalCounterReporter interface { + reportInterval(counter *intervalCounterImpl, intervalStartUTC int64, values map[string]uint64) +} + +func newIntervalCounter(name string, + intervalSize time.Duration, + reporter intervalCounterReporter, + flushFreq time.Duration, + ageThreshold time.Duration, + disposeF func()) IntervalCounter { + + currentInterval := time.Now().Truncate(intervalSize).UTC().Unix() + currentCounters := make(map[string]uint64) + intervalMap := make(map[int64]map[string]uint64) + intervalMap[currentInterval] = currentCounters + + var ticker *time.Ticker + if flushFreq > 0 { + ticker = time.NewTicker(flushFreq) + } + + intervalCounter := &intervalCounterImpl{ + name: name, + intervalSize: intervalSize, + currentInterval: currentInterval, + currentValues: currentCounters, + intervalMap: intervalMap, + eventChan: make(chan interface{}, 10), + reporter: reporter, + ticker: ticker, + ageThreshold: ageThreshold, + dispose: disposeF, + } + + go intervalCounter.run() + if ticker != nil { + go intervalCounter.startTicker() + } + return intervalCounter +} + +type counterEvent struct { + intervalId string + time time.Time + value uint64 +} + +type shutdownEvent struct{} + +type intervalCounterImpl struct { + name string + intervalSize time.Duration + currentInterval int64 + currentValues map[string]uint64 + intervalMap map[int64]map[string]uint64 + eventChan chan interface{} + reporter intervalCounterReporter + ticker *time.Ticker + ageThreshold time.Duration + dispose func() +} + +func (intervalCounter *intervalCounterImpl) Update(intervalId string, time time.Time, value uint64) { + event := &counterEvent{intervalId, time, value} + + // Select on this to make sure we don't block? If blocked, log to disk instead? Map updates should be + // very fast, not sure that's needed + intervalCounter.eventChan <- event +} + +func (intervalCounter *intervalCounterImpl) Dispose() { + intervalCounter.dispose() + intervalCounter.eventChan <- &shutdownEvent{} +} + +func (intervalCounter *intervalCounterImpl) report() { + intervalCounter.eventChan <- time.Now() +} + +func (intervalCounter *intervalCounterImpl) startTicker() { + for event := range intervalCounter.ticker.C { + intervalCounter.eventChan <- event + } +} + +func (intervalCounter *intervalCounterImpl) run() { + defer fmt.Println("Interval intervalCounter shutting down") + + for i := range intervalCounter.eventChan { + switch event := i.(type) { + case *counterEvent: + interval := event.time.Truncate(intervalCounter.intervalSize).UTC().Unix() + valueMap := intervalCounter.getValueMapForInterval(interval) + valueMap[event.intervalId] += event.value + break + case time.Time: + intervalCounter.flushIntervals() + case *shutdownEvent: + if intervalCounter.ticker != nil { + intervalCounter.ticker.Stop() + } + intervalCounter.currentValues = nil + intervalCounter.intervalMap = nil + return + default: + pfxlog.Logger().Errorf("unhandled IntervalCounter event type '%v'", reflect.TypeOf(event).Name()) + } + } +} + +func (intervalCounter *intervalCounterImpl) getValueMapForInterval(interval int64) map[string]uint64 { + if intervalCounter.currentInterval == interval { + return intervalCounter.currentValues + } + + if result, found := intervalCounter.intervalMap[interval]; found { + return result + } + + result := make(map[string]uint64) + intervalCounter.intervalMap[interval] = result + + if interval > intervalCounter.currentInterval { + intervalCounter.currentInterval = interval + intervalCounter.currentValues = result + } + + return result +} + +func (intervalCounter *intervalCounterImpl) flushIntervals() { + threshold := time.Now().UTC().Add(-intervalCounter.ageThreshold).Unix() + + for interval, values := range intervalCounter.intervalMap { + if interval < intervalCounter.currentInterval || interval <= threshold { + if len(values) > 0 { + intervalCounter.reporter.reportInterval(intervalCounter, interval, values) + if interval == intervalCounter.currentInterval { + intervalCounter.currentValues = make(map[string]uint64) + intervalCounter.intervalMap[intervalCounter.currentInterval] = intervalCounter.currentValues + } else { + delete(intervalCounter.intervalMap, interval) + } + } + } + } +} diff --git a/fabric/metrics/interval_counter_test.go b/fabric/metrics/interval_counter_test.go new file mode 100644 index 000000000..a1a6d2dbc --- /dev/null +++ b/fabric/metrics/interval_counter_test.go @@ -0,0 +1,176 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "fmt" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "sort" + "testing" + "time" +) + +type collectingReporter struct { + intervalChan chan *intervalEvent +} + +type intervalEvent struct { + intervalStartUTC int64 + intervalEndUTC int64 + values map[string]uint64 +} + +type intervalSlice []*intervalEvent + +func (s intervalSlice) Len() int { + return len(([]*intervalEvent)(s)) +} + +func (s intervalSlice) Less(i, j int) bool { + slice := ([]*intervalEvent)(s) + return slice[i].intervalStartUTC < slice[j].intervalStartUTC +} + +func (s intervalSlice) Swap(i, j int) { + slice := ([]*intervalEvent)(s) + tmp := slice[i] + slice[i] = slice[j] + slice[j] = tmp +} + +func (reporter *collectingReporter) reportInterval(counter *intervalCounterImpl, intervalStartUTC int64, values map[string]uint64) { + i := &intervalEvent{ + intervalStartUTC: intervalStartUTC, + intervalEndUTC: intervalStartUTC + int64(counter.intervalSize.Seconds()), + values: values, + } + + reporter.intervalChan <- i +} + +func (reporter *collectingReporter) GetNextIntervals(eventCount uint32, timeout time.Duration) []*intervalEvent { + count := uint32(0) + var intervals []*intervalEvent + for count < eventCount { + select { + case next := <-reporter.intervalChan: + count++ + intervals = append(intervals, next) + case <-time.After(timeout): + return intervals + } + } + return intervals +} + +func TestTrackerNonDuplicate(t *testing.T) { + assert := require.New(t) + + reporter := &collectingReporter{intervalChan: make(chan *intervalEvent)} + + intervalCounter := newIntervalCounter( + "usage", time.Minute, reporter, time.Duration(0), time.Duration(0), func() {}).(*intervalCounterImpl) + + currentMinute := time.Now().Truncate(time.Minute) + + intervalID1 := uuid.New().String() + intervalCounter.Update(intervalID1, currentMinute.Add(time.Second*5), 11111) + intervalCounter.report() + + intervals := reporter.GetNextIntervals(1, time.Second) + + assert.Equal(1, len(intervals)) + interval := intervals[0] + assert.Equal(currentMinute.UTC().Unix(), interval.intervalStartUTC) + assert.Equal(currentMinute.Add(time.Minute).UTC().Unix(), interval.intervalEndUTC) + assert.Equal(1, len(interval.values)) + assert.Equal(uint64(11111), interval.values[intervalID1]) + + // verify that we don't see any new events + intervalCounter.report() + + intervals = reporter.GetNextIntervals(1, time.Millisecond*50) + assert.Equal(0, len(intervals)) + + intervalID2 := uuid.New().String() + + // interval N + intervalCounter.Update(intervalID1, currentMinute.Add(time.Second*5), 10) + intervalCounter.Update(intervalID2, currentMinute.Add(time.Second*6), 11) + + intervalCounter.Update(intervalID1, currentMinute.Add(time.Second*25), 15) + intervalCounter.Update(intervalID2, currentMinute.Add(time.Second*26), 17) + + intervalCounter.Update(intervalID1, currentMinute.Add(time.Second*31), 40) + intervalCounter.Update(intervalID2, currentMinute.Add(time.Second*31), 50) + + // interval N+1 + intervalCounter.Update(intervalID1, currentMinute.Add(time.Second*62), 22) + intervalCounter.Update(intervalID2, currentMinute.Add(time.Second*62), 23) + + // interval N-1 + intervalCounter.Update(intervalID1, currentMinute.Add(-time.Second*30), 123) + intervalCounter.Update(intervalID1, currentMinute.Add(-1), 77) + intervalCounter.Update(intervalID2, currentMinute.Add(-time.Second*30), 321) + + // interval N-2 + intervalCounter.Update(intervalID1, currentMinute.Add(-time.Second*70), 234) + + // interval N-3 + intervalCounter.Update(intervalID2, currentMinute.Add(-time.Second*121), 567) + + intervalCounter.report() + + intervals = reporter.GetNextIntervals(5, time.Millisecond*50) + fmt.Printf("Current minute: %v\n", currentMinute.UTC().Unix()) + for _, interval = range intervals { + fmt.Printf("Interval: %v\n", interval.intervalStartUTC) + } + assert.Equal(4, len(intervals)) // Future minutes won't be reported + sort.Sort(intervalSlice(intervals)) + + // interval N-3 + interval = intervals[0] + assert.Equal(currentMinute.Add(time.Minute * - 3).UTC().Unix(), interval.intervalStartUTC) + assert.Equal(currentMinute.Add(time.Minute * - 2).UTC().Unix(), interval.intervalEndUTC) + assert.Equal(1, len(interval.values)) + assert.Equal(uint64(567), interval.values[intervalID2]) + + // interval N-2 + interval = intervals[1] + assert.Equal(currentMinute.Add(time.Minute * - 2).UTC().Unix(), interval.intervalStartUTC) + assert.Equal(currentMinute.Add(time.Minute * - 1).UTC().Unix(), interval.intervalEndUTC) + assert.Equal(1, len(interval.values)) + assert.Equal(uint64(234), interval.values[intervalID1]) + + // interval N-1 + interval = intervals[2] + assert.Equal(currentMinute.Add(time.Minute * - 1).UTC().Unix(), interval.intervalStartUTC) + assert.Equal(currentMinute.UTC().Unix(), interval.intervalEndUTC) + assert.Equal(2, len(interval.values)) + assert.Equal(uint64(200), interval.values[intervalID1]) + assert.Equal(uint64(321), interval.values[intervalID2]) + + // interval N + interval = intervals[3] + assert.Equal(currentMinute.UTC().Unix(), interval.intervalStartUTC) + assert.Equal(currentMinute.Add(time.Minute).UTC().Unix(), interval.intervalEndUTC) + assert.Equal(2, len(interval.values)) + assert.Equal(uint64(65), interval.values[intervalID1]) + assert.Equal(uint64(78), interval.values[intervalID2]) +} diff --git a/fabric/metrics/latency.go b/fabric/metrics/latency.go new file mode 100644 index 000000000..d21b6cb37 --- /dev/null +++ b/fabric/metrics/latency.go @@ -0,0 +1,80 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/util/info" + "github.com/michaelquigley/pfxlog" + "time" +) + +// send regular latency probes +// +func ProbeLatency(ch channel2.Channel, histogram Histogram, interval time.Duration) { + log := pfxlog.ContextLogger(ch.Label()) + log.Info("started") + defer log.Warn("exited") + defer func() { + histogram.Dispose() + }() + + lastSend := info.NowInMilliseconds() + for { + time.Sleep(interval) + if ch.IsClosed() { + return + } + + now := info.NowInMilliseconds() + if now-lastSend > 10000 { + lastSend = now + request := channel2.NewMessage(channel2.ContentTypeLatencyType, nil) + request.PutUint64Header(latencyProbeTime, uint64(time.Now().UnixNano())) + waitCh, err := ch.SendAndWaitWithPriority(request, channel2.High) + if err != nil { + log.Errorf("unexpected error sending latency probe (%s)", err) + continue + } + + select { + case response := <-waitCh: + if response == nil { + log.Error("wait channel closed") + return + } + if response.ContentType == channel2.ContentTypeResultType { + result := channel2.UnmarshalResult(response) + if result.Success { + if sentTime, ok := response.GetUint64Header(latencyProbeTime); ok { + latency := time.Now().UnixNano() - int64(sentTime) + histogram.Update(latency) + } else { + log.Error("no send time") + } + } else { + log.Error("failed latency response") + } + } else { + log.Errorf("unexpected latency response [%d]", response.ContentType) + } + case <-time.After(time.Second * 5): + log.Error("latency timeout") + } + } + } +} diff --git a/fabric/metrics/meter.go b/fabric/metrics/meter.go new file mode 100644 index 000000000..7a4749504 --- /dev/null +++ b/fabric/metrics/meter.go @@ -0,0 +1,35 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import "github.com/rcrowley/go-metrics" + +// Meter represents a metric which is measuring a count and a rate +type Meter interface { + Metric + Mark(int64) +} + +type meterImpl struct { + metrics.Meter + dispose func() +} + +func (meter *meterImpl) Dispose() { + meter.Stop() + meter.dispose() +} diff --git a/fabric/metrics/metrics_msg_builder.go b/fabric/metrics/metrics_msg_builder.go new file mode 100644 index 000000000..004ccbaef --- /dev/null +++ b/fabric/metrics/metrics_msg_builder.go @@ -0,0 +1,117 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/golang/protobuf/ptypes" + "github.com/michaelquigley/pfxlog" + "github.com/rcrowley/go-metrics" + "time" +) + +type messageBuilder ctrl_pb.MetricsMessage + +func newMessageBuilder(sourceType ctrl_pb.MetricsSourceType, sourceId string, tags map[string]string) *messageBuilder { + now := time.Now() + nowTS, err := ptypes.TimestampProto(now) + if err != nil { + pfxlog.Logger().Errorf("The now time (%v) is out of range for valid timestamps. Your clock is wrong", now) + } + builder := &messageBuilder{Timestamp: nowTS} + builder.SourceType = sourceType + builder.SourceId = sourceId + builder.Tags = tags + + return builder +} + +func (builder *messageBuilder) addIntValue(name string, value int64) { + if builder.IntValues == nil { + builder.IntValues = make(map[string]int64) + } + builder.IntValues[name] = value +} + +func (builder *messageBuilder) addCounter(name string, metric metrics.Counter) { + builder.addIntValue(name, metric.Count()) +} + +func (builder *messageBuilder) addIntGauge(name string, metric metrics.Gauge) { + builder.addIntValue(name, metric.Value()) +} + +func (builder *messageBuilder) addFloatGauge(name string, metric metrics.GaugeFloat64) { + if builder.FloatValues == nil { + builder.FloatValues = make(map[string]float64) + } + builder.FloatValues[name] = metric.Value() +} + +func (builder *messageBuilder) addMeter(name string, metric metrics.Meter) { + meter := &ctrl_pb.MetricsMessage_Meter{} + meter.Count = metric.Count() + meter.M1Rate = metric.Rate1() + meter.M5Rate = metric.Rate5() + meter.M15Rate = metric.Rate15() + meter.MeanRate = metric.RateMean() + + if builder.Meters == nil { + builder.Meters = make(map[string]*ctrl_pb.MetricsMessage_Meter) + } + + builder.Meters[name] = meter +} + +func (builder *messageBuilder) addHistogram(name string, metric metrics.Histogram) { + histogram := &ctrl_pb.MetricsMessage_Histogram{} + histogram.Count = metric.Count() + histogram.Max = metric.Max() + histogram.Mean = metric.Mean() + histogram.Min = metric.Min() + histogram.StdDev = metric.StdDev() + histogram.Variance = metric.Variance() + + ps := metric.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}) + + histogram.P50 = ps[0] + histogram.P75 = ps[1] + histogram.P95 = ps[2] + histogram.P99 = ps[3] + histogram.P999 = ps[4] + histogram.P9999 = ps[5] + + if builder.Histograms == nil { + builder.Histograms = make(map[string]*ctrl_pb.MetricsMessage_Histogram) + } + + builder.Histograms[name] = histogram +} + +func (builder *messageBuilder) addIntervalBucketEvents(events []*bucketEvent) { + for _, event := range events { + if builder.IntervalCounters == nil { + builder.IntervalCounters = make(map[string]*ctrl_pb.MetricsMessage_IntervalCounter) + } + counter, present := builder.IntervalCounters[event.name] + if !present { + builder.IntervalCounters[event.name] = event.interval + } else { + counter.Buckets = append(counter.Buckets, event.interval.Buckets...) + } + } +} diff --git a/fabric/metrics/peekhandler.go b/fabric/metrics/peekhandler.go new file mode 100644 index 000000000..b0df59f24 --- /dev/null +++ b/fabric/metrics/peekhandler.go @@ -0,0 +1,237 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/michaelquigley/pfxlog" + "time" +) + +const ( + latencyProbeTime = 128 +) + +// NewChannelPeekHandler creates a channel PeekHandler which tracks latency, message rate and message size distribution +func NewChannelPeekHandler(linkId string, registry Registry) channel2.PeekHandler { + appTxBytesMeter := registry.Meter("fabric.tx.bytesrate") + appTxMsgMeter := registry.Meter("fabric.tx.msgrate") + appTxMsgSizeHistogram := registry.Histogram("fabric.tx.msgsize") + + appRxBytesMeter := registry.Meter("fabric.rx.bytesrate") + appRxMsgMeter := registry.Meter("fabric.rx.msgrate") + appRxMsgSizeHistogram := registry.Histogram("fabric.rx.msgsize") + + linkTxBytesMeter := registry.Meter("link." + linkId + ".tx.bytesrate") + linkTxMsgMeter := registry.Meter("link." + linkId + ".tx.msgrate") + linkTxMsgSizeHistogram := registry.Histogram("link." + linkId + ".tx.msgsize") + linkRxBytesMeter := registry.Meter("link." + linkId + ".rx.bytesrate") + linkRxMsgMeter := registry.Meter("link." + linkId + ".rx.msgrate") + linkRxMsgSizeHistogram := registry.Histogram("link." + linkId + ".rx.msgsize") + + usageRxCounter := registry.IntervalCounter("usage.fabric.rx", time.Minute) + usageTxCounter := registry.IntervalCounter("usage.fabric.tx", time.Minute) + + closeHook := func() { + linkTxBytesMeter.Dispose() + linkTxMsgMeter.Dispose() + linkTxMsgSizeHistogram.Dispose() + linkRxBytesMeter.Dispose() + linkRxMsgMeter.Dispose() + linkRxMsgSizeHistogram.Dispose() + // app level metrics and usageCounter are shared across all links, so we don't dispose of them + } + + return &channelPeekHandler{ + appTxBytesMeter: appTxBytesMeter, + appTxMsgMeter: appTxMsgMeter, + appTxMsgSizeHistogram: appTxMsgSizeHistogram, + appRxBytesMeter: appRxBytesMeter, + appRxMsgMeter: appRxMsgMeter, + appRxMsgSizeHistogram: appRxMsgSizeHistogram, + linkTxBytesMeter: linkTxBytesMeter, + linkTxMsgMeter: linkTxMsgMeter, + linkTxMsgSizeHistogram: linkTxMsgSizeHistogram, + linkRxBytesMeter: linkRxBytesMeter, + linkRxMsgMeter: linkRxMsgMeter, + linkRxMsgSizeHistogram: linkRxMsgSizeHistogram, + usageRxCounter: usageRxCounter, + usageTxCounter: usageTxCounter, + closeHook: closeHook, + } +} + +type channelPeekHandler struct { + appTxBytesMeter Meter + appTxMsgMeter Meter + appRxBytesMeter Meter + appRxMsgMeter Meter + + appTxMsgSizeHistogram Histogram + appRxMsgSizeHistogram Histogram + + linkLatencyHistogram Histogram + linkTxBytesMeter Meter + linkTxMsgMeter Meter + linkRxBytesMeter Meter + linkRxMsgMeter Meter + linkTxMsgSizeHistogram Histogram + linkRxMsgSizeHistogram Histogram + + usageRxCounter IntervalCounter + usageTxCounter IntervalCounter + + closeHook func() +} + +func (h *channelPeekHandler) Connect(ch channel2.Channel, remoteAddress string) { +} + +func (h *channelPeekHandler) Rx(msg *channel2.Message, ch channel2.Channel) { + msgSize := int64(len(msg.Body)) + h.linkRxBytesMeter.Mark(msgSize) + h.linkRxMsgMeter.Mark(1) + h.linkRxMsgSizeHistogram.Update(msgSize) + h.appRxBytesMeter.Mark(msgSize) + h.appRxMsgMeter.Mark(1) + h.appRxMsgSizeHistogram.Update(msgSize) + + if msg.ContentType == int32(xgress.ContentTypePayloadType) { + if payload, err := xgress.UnmarshallPayload(msg); err != nil { + pfxlog.Logger().Errorf("Failed to unmarshal payload. Error: %v", err) + } else { + h.usageRxCounter.Update(payload.SessionId, time.Now(), uint64(len(payload.Data))) + } + } +} + +func (h *channelPeekHandler) Tx(msg *channel2.Message, ch channel2.Channel) { + msgSize := int64(len(msg.Body)) + h.linkTxBytesMeter.Mark(msgSize) + h.linkTxMsgMeter.Mark(1) + h.linkTxMsgSizeHistogram.Update(msgSize) + h.appTxBytesMeter.Mark(msgSize) + h.appTxMsgMeter.Mark(1) + h.appTxMsgSizeHistogram.Update(msgSize) + + if msg.ContentType == int32(xgress.ContentTypePayloadType) { + if payload, err := xgress.UnmarshallPayload(msg); err != nil { + pfxlog.Logger().Errorf("Failed to unmarshal payload. Error: %v", err) + } else { + h.usageTxCounter.Update(payload.SessionId, time.Now(), uint64(len(payload.Data))) + } + } +} + +func (h *channelPeekHandler) Close(ch channel2.Channel) { + if h.closeHook != nil { + h.closeHook() + } +} + +// NewXgressPeekHandler creates an xgress PeekHandler which tracks message rates and histograms as well as usage +func NewXgressPeekHandler(registry Registry) xgress.PeekHandler { + ingressTxBytesMeter := registry.Meter("ingress.tx.bytesrate") + ingressTxMsgMeter := registry.Meter("ingress.tx.msgrate") + ingressRxBytesMeter := registry.Meter("ingress.rx.bytesrate") + ingressRxMsgMeter := registry.Meter("ingress.rx.msgrate") + egressTxBytesMeter := registry.Meter("egress.tx.bytesrate") + egressTxMsgMeter := registry.Meter("egress.tx.Msgrate") + egressRxBytesMeter := registry.Meter("egress.rx.bytesrate") + egressRxMsgMeter := registry.Meter("egress.rx.msgrate") + + ingressTxMsgSizeHistogram := registry.Histogram("ingress.tx.msgsize") + ingressRxMsgSizeHistogram := registry.Histogram("ingress.rx.msgsize") + egressTxMsgSizeHistogram := registry.Histogram("egress.tx.msgsize") + egressRxMsgSizeHistogram := registry.Histogram("egress.rx.msgsize") + + return &xgressPeekHandler{ + ingressTxBytesMeter: ingressTxBytesMeter, + ingressTxMsgMeter: ingressTxMsgMeter, + ingressRxBytesMeter: ingressRxBytesMeter, + ingressRxMsgMeter: ingressRxMsgMeter, + egressTxBytesMeter: egressTxBytesMeter, + egressTxMsgMeter: egressTxMsgMeter, + egressRxBytesMeter: egressRxBytesMeter, + egressRxMsgMeter: egressRxMsgMeter, + + ingressTxMsgSizeHistogram: ingressTxMsgSizeHistogram, + ingressRxMsgSizeHistogram: ingressRxMsgSizeHistogram, + egressTxMsgSizeHistogram: egressTxMsgSizeHistogram, + egressRxMsgSizeHistogram: egressRxMsgSizeHistogram, + + ingressRxUsageCounter: registry.IntervalCounter("usage.ingress.rx", time.Minute), + ingressTxUsageCounter: registry.IntervalCounter("usage.ingress.tx", time.Minute), + egressRxUsageCounter: registry.IntervalCounter("usage.egress.rx", time.Minute), + egressTxUsageCounter: registry.IntervalCounter("usage.egress.tx", time.Minute), + } +} + +type xgressPeekHandler struct { + ingressTxBytesMeter Meter + ingressTxMsgMeter Meter + ingressRxBytesMeter Meter + ingressRxMsgMeter Meter + egressTxBytesMeter Meter + egressTxMsgMeter Meter + egressRxBytesMeter Meter + egressRxMsgMeter Meter + + ingressTxMsgSizeHistogram Histogram + ingressRxMsgSizeHistogram Histogram + egressTxMsgSizeHistogram Histogram + egressRxMsgSizeHistogram Histogram + + ingressRxUsageCounter IntervalCounter + ingressTxUsageCounter IntervalCounter + egressRxUsageCounter IntervalCounter + egressTxUsageCounter IntervalCounter +} + +func (handler *xgressPeekHandler) Rx(x *xgress.Xgress, payload *xgress.Payload) { + msgSize := int64(len(payload.Data)) + if x.Originator() == xgress.Initiator { + handler.ingressRxUsageCounter.Update(x.SessionId().Token, time.Now(), uint64(msgSize)) + handler.ingressRxMsgMeter.Mark(1) + handler.ingressRxBytesMeter.Mark(msgSize) + handler.ingressRxMsgSizeHistogram.Update(msgSize) + } else { + handler.egressRxUsageCounter.Update(x.SessionId().Token, time.Now(), uint64(msgSize)) + handler.egressRxMsgMeter.Mark(1) + handler.egressRxBytesMeter.Mark(msgSize) + handler.egressRxMsgSizeHistogram.Update(msgSize) + } +} + +func (handler *xgressPeekHandler) Tx(x *xgress.Xgress, payload *xgress.Payload) { + msgSize := int64(len(payload.Data)) + if x.Originator() == xgress.Initiator { + handler.ingressTxUsageCounter.Update(x.SessionId().Token, time.Now(), uint64(msgSize)) + handler.ingressTxMsgMeter.Mark(1) + handler.ingressTxBytesMeter.Mark(msgSize) + handler.ingressTxMsgSizeHistogram.Update(msgSize) + } else { + handler.egressTxUsageCounter.Update(x.SessionId().Token, time.Now(), uint64(msgSize)) + handler.egressTxMsgMeter.Mark(1) + handler.egressTxBytesMeter.Mark(msgSize) + handler.egressTxMsgSizeHistogram.Update(msgSize) + } +} + +func (handler *xgressPeekHandler) Close(x *xgress.Xgress) { +} diff --git a/fabric/metrics/registry.go b/fabric/metrics/registry.go new file mode 100644 index 000000000..c98522a6f --- /dev/null +++ b/fabric/metrics/registry.go @@ -0,0 +1,203 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package metrics + +import ( + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/orcaman/concurrent-map" + "github.com/rcrowley/go-metrics" + "reflect" + "time" +) + +// Metric is the base functionality for all metrics types +type Metric interface { + Dispose() +} + +// Registry allows for configuring and accessing metrics for a fabric application +type Registry interface { + SourceId() string + Meter(name string) Meter + Histogram(name string) Histogram + IntervalCounter(name string, intervalSize time.Duration) IntervalCounter + Each(visitor func(name string, metric Metric)) + EventController() EventController +} + +// NewRegistry create a new metrics registry instance +func NewRegistry(sourceType ctrl_pb.MetricsSourceType, sourceId string, tags map[string]string, reportInterval time.Duration, cfg *Config) Registry { + registry := ®istryImpl{ + sourceType: sourceType, + sourceId: sourceId, + tags: tags, + metricMap: cmap.New(), + eventController: NewEventController(cfg), + intervalBucketChan: make(chan *bucketEvent, 1), + } + + go registry.run(reportInterval) + + return registry +} + +type bucketEvent struct { + interval *ctrl_pb.MetricsMessage_IntervalCounter + name string +} + +type registryImpl struct { + sourceType ctrl_pb.MetricsSourceType + sourceId string + tags map[string]string + metricMap cmap.ConcurrentMap + eventController EventController + intervalBucketChan chan *bucketEvent + intervalBuckets []*bucketEvent +} + +func (registry *registryImpl) run(reportInterval time.Duration) { + ticker := time.Tick(reportInterval) + + for { + select { + case interval := <-registry.intervalBucketChan: + registry.intervalBuckets = append(registry.intervalBuckets, interval) + case <-ticker: + registry.report() + } + } +} + +func (registry *registryImpl) dispose(name string) { + registry.metricMap.Remove(name) +} + +func (registry *registryImpl) EventController() EventController { + return registry.eventController +} + +func (registry *registryImpl) SourceId() string { + return registry.sourceId +} + +func (registry *registryImpl) Meter(name string) Meter { + metric, present := registry.metricMap.Get(name) + if present { + meter, ok := metric.(Meter) + if !ok { + panic(fmt.Errorf("metric '%v' already exists and is not a meter. It is a %v", name, reflect.TypeOf(metric).Name())) + } + return meter + } + + meter := &meterImpl{ + Meter: metrics.NewMeter(), + dispose: func() { + registry.dispose(name) + }, + } + registry.metricMap.Set(name, meter) + return meter +} + +func (registry *registryImpl) Histogram(name string) Histogram { + metric, present := registry.metricMap.Get(name) + if present { + histogram, ok := metric.(Histogram) + if !ok { + panic(fmt.Errorf("metric '%v' already exists and is not a histogram. It is a %v", name, reflect.TypeOf(metric).Name())) + } + return histogram + } + + histogram := &histogramImpl{ + Histogram: metrics.NewHistogram(metrics.Sample(metrics.NewExpDecaySample(128, 0.015))), + dispose: func() { + registry.dispose(name) + }, + } + registry.metricMap.Set(name, histogram) + return histogram +} + +// NewIntervalCounter creates an IntervalCounter +func (registry *registryImpl) IntervalCounter(name string, intervalSize time.Duration) IntervalCounter { + metric, present := registry.metricMap.Get(name) + if present { + intervalCounter, ok := metric.(IntervalCounter) + if !ok { + panic(fmt.Errorf("metric '%v' already exists and is not an interval counter. It is a %v", name, reflect.TypeOf(metric).Name())) + } + return intervalCounter + } + + disposeF := func() { registry.dispose(name) } + intervalCounter := newIntervalCounter(name, intervalSize, registry, time.Minute, time.Second*80, disposeF) + registry.metricMap.Set(name, intervalCounter) + return intervalCounter +} + +func (registry *registryImpl) Each(visitor func(name string, metric Metric)) { + for entry := range registry.metricMap.IterBuffered() { + visitor(entry.Key, entry.Val.(Metric)) + } +} + +func (registry *registryImpl) reportInterval(counter *intervalCounterImpl, intervalStartUTC int64, values map[string]uint64) { + bucket := &ctrl_pb.MetricsMessage_IntervalBucket{ + IntervalStartUTC: intervalStartUTC, + Values: values, + } + + interval := &ctrl_pb.MetricsMessage_IntervalCounter{ + IntervalLength: uint64(counter.intervalSize.Seconds()), + Buckets: []*ctrl_pb.MetricsMessage_IntervalBucket{bucket}, + } + + bucketEvent := &bucketEvent{ + interval: interval, + name: counter.name, + } + + registry.intervalBucketChan <- bucketEvent +} + +func (registry *registryImpl) report() { + builder := newMessageBuilder(registry.sourceType, registry.sourceId, registry.tags) + + registry.Each(func(name string, i Metric) { + switch metric := i.(type) { + case *meterImpl: + builder.addMeter(name, metric.Snapshot()) + case *histogramImpl: + builder.addHistogram(name, metric.Snapshot()) + case *intervalCounterImpl: + // ignore, handled below + default: + pfxlog.Logger().Errorf("Unsupported metric type %v", reflect.TypeOf(i)) + } + }) + + builder.addIntervalBucketEvents(registry.intervalBuckets) + registry.intervalBuckets = nil + + msg := (*ctrl_pb.MetricsMessage)(builder) + registry.eventController.AcceptMetrics(msg) +} diff --git a/fabric/pb/ctrl_pb/ctrl.pb.go b/fabric/pb/ctrl_pb/ctrl.pb.go new file mode 100644 index 000000000..db08ea2d1 --- /dev/null +++ b/fabric/pb/ctrl_pb/ctrl.pb.go @@ -0,0 +1,1303 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: ctrl.proto + +package ctrl_pb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import timestamp "github.com/golang/protobuf/ptypes/timestamp" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type ContentType int32 + +const ( + ContentType_Zero ContentType = 0 + ContentType_SessionRequestType ContentType = 1000 + ContentType_SessionSuccessType ContentType = 1001 + ContentType_DialType ContentType = 1002 + ContentType_LinkType ContentType = 1003 + ContentType_FaultType ContentType = 1004 + ContentType_RouteType ContentType = 1005 + ContentType_UnrouteType ContentType = 1006 + ContentType_MetricsType ContentType = 1007 + ContentType_TogglePipeTracesRequestType ContentType = 1008 + ContentType_TraceEventType ContentType = 1010 + ContentType_BindRequestType ContentType = 1011 + ContentType_BindResponseType ContentType = 1012 + ContentType_InspectRequestType ContentType = 1013 + ContentType_InspectResponseType ContentType = 1014 + ContentType_StartXgressType ContentType = 1015 + ContentType_SessionFailedType ContentType = 1016 +) + +var ContentType_name = map[int32]string{ + 0: "Zero", + 1000: "SessionRequestType", + 1001: "SessionSuccessType", + 1002: "DialType", + 1003: "LinkType", + 1004: "FaultType", + 1005: "RouteType", + 1006: "UnrouteType", + 1007: "MetricsType", + 1008: "TogglePipeTracesRequestType", + 1010: "TraceEventType", + 1011: "BindRequestType", + 1012: "BindResponseType", + 1013: "InspectRequestType", + 1014: "InspectResponseType", + 1015: "StartXgressType", + 1016: "SessionFailedType", +} +var ContentType_value = map[string]int32{ + "Zero": 0, + "SessionRequestType": 1000, + "SessionSuccessType": 1001, + "DialType": 1002, + "LinkType": 1003, + "FaultType": 1004, + "RouteType": 1005, + "UnrouteType": 1006, + "MetricsType": 1007, + "TogglePipeTracesRequestType": 1008, + "TraceEventType": 1010, + "BindRequestType": 1011, + "BindResponseType": 1012, + "InspectRequestType": 1013, + "InspectResponseType": 1014, + "StartXgressType": 1015, + "SessionFailedType": 1016, +} + +func (x ContentType) String() string { + return proto.EnumName(ContentType_name, int32(x)) +} +func (ContentType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{0} +} + +type BindType int32 + +const ( + BindType_Bind BindType = 0 + BindType_Unbind BindType = 1 +) + +var BindType_name = map[int32]string{ + 0: "Bind", + 1: "Unbind", +} +var BindType_value = map[string]int32{ + "Bind": 0, + "Unbind": 1, +} + +func (x BindType) String() string { + return proto.EnumName(BindType_name, int32(x)) +} +func (BindType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{1} +} + +type FaultSubject int32 + +const ( + FaultSubject_IngressFault FaultSubject = 0 + FaultSubject_EgressFault FaultSubject = 1 + FaultSubject_LinkFault FaultSubject = 2 +) + +var FaultSubject_name = map[int32]string{ + 0: "IngressFault", + 1: "EgressFault", + 2: "LinkFault", +} +var FaultSubject_value = map[string]int32{ + "IngressFault": 0, + "EgressFault": 1, + "LinkFault": 2, +} + +func (x FaultSubject) String() string { + return proto.EnumName(FaultSubject_name, int32(x)) +} +func (FaultSubject) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{2} +} + +type MetricsSourceType int32 + +const ( + MetricsSourceType_Ingress MetricsSourceType = 0 + MetricsSourceType_Egress MetricsSourceType = 1 + MetricsSourceType_Internal MetricsSourceType = 2 +) + +var MetricsSourceType_name = map[int32]string{ + 0: "Ingress", + 1: "Egress", + 2: "Internal", +} +var MetricsSourceType_value = map[string]int32{ + "Ingress": 0, + "Egress": 1, + "Internal": 2, +} + +func (x MetricsSourceType) String() string { + return proto.EnumName(MetricsSourceType_name, int32(x)) +} +func (MetricsSourceType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{3} +} + +type SessionRequest struct { + IngressId string `protobuf:"bytes,1,opt,name=ingressId,proto3" json:"ingressId,omitempty"` + ServiceId string `protobuf:"bytes,2,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SessionRequest) Reset() { *m = SessionRequest{} } +func (m *SessionRequest) String() string { return proto.CompactTextString(m) } +func (*SessionRequest) ProtoMessage() {} +func (*SessionRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{0} +} +func (m *SessionRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SessionRequest.Unmarshal(m, b) +} +func (m *SessionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SessionRequest.Marshal(b, m, deterministic) +} +func (dst *SessionRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SessionRequest.Merge(dst, src) +} +func (m *SessionRequest) XXX_Size() int { + return xxx_messageInfo_SessionRequest.Size(m) +} +func (m *SessionRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SessionRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SessionRequest proto.InternalMessageInfo + +func (m *SessionRequest) GetIngressId() string { + if m != nil { + return m.IngressId + } + return "" +} + +func (m *SessionRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +type BindRequest struct { + BindType BindType `protobuf:"varint,1,opt,name=bindType,proto3,enum=ctrl.pb.BindType" json:"bindType,omitempty"` + Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"` + ServiceId string `protobuf:"bytes,3,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BindRequest) Reset() { *m = BindRequest{} } +func (m *BindRequest) String() string { return proto.CompactTextString(m) } +func (*BindRequest) ProtoMessage() {} +func (*BindRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{1} +} +func (m *BindRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BindRequest.Unmarshal(m, b) +} +func (m *BindRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BindRequest.Marshal(b, m, deterministic) +} +func (dst *BindRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_BindRequest.Merge(dst, src) +} +func (m *BindRequest) XXX_Size() int { + return xxx_messageInfo_BindRequest.Size(m) +} +func (m *BindRequest) XXX_DiscardUnknown() { + xxx_messageInfo_BindRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_BindRequest proto.InternalMessageInfo + +func (m *BindRequest) GetBindType() BindType { + if m != nil { + return m.BindType + } + return BindType_Bind +} + +func (m *BindRequest) GetToken() string { + if m != nil { + return m.Token + } + return "" +} + +func (m *BindRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +type BindResponse struct { + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *BindResponse) Reset() { *m = BindResponse{} } +func (m *BindResponse) String() string { return proto.CompactTextString(m) } +func (*BindResponse) ProtoMessage() {} +func (*BindResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{2} +} +func (m *BindResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_BindResponse.Unmarshal(m, b) +} +func (m *BindResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_BindResponse.Marshal(b, m, deterministic) +} +func (dst *BindResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_BindResponse.Merge(dst, src) +} +func (m *BindResponse) XXX_Size() int { + return xxx_messageInfo_BindResponse.Size(m) +} +func (m *BindResponse) XXX_DiscardUnknown() { + xxx_messageInfo_BindResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_BindResponse proto.InternalMessageInfo + +func (m *BindResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *BindResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +type Dial struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Dial) Reset() { *m = Dial{} } +func (m *Dial) String() string { return proto.CompactTextString(m) } +func (*Dial) ProtoMessage() {} +func (*Dial) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{3} +} +func (m *Dial) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Dial.Unmarshal(m, b) +} +func (m *Dial) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Dial.Marshal(b, m, deterministic) +} +func (dst *Dial) XXX_Merge(src proto.Message) { + xxx_messageInfo_Dial.Merge(dst, src) +} +func (m *Dial) XXX_Size() int { + return xxx_messageInfo_Dial.Size(m) +} +func (m *Dial) XXX_DiscardUnknown() { + xxx_messageInfo_Dial.DiscardUnknown(m) +} + +var xxx_messageInfo_Dial proto.InternalMessageInfo + +func (m *Dial) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Dial) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type Link struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Link) Reset() { *m = Link{} } +func (m *Link) String() string { return proto.CompactTextString(m) } +func (*Link) ProtoMessage() {} +func (*Link) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{4} +} +func (m *Link) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Link.Unmarshal(m, b) +} +func (m *Link) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Link.Marshal(b, m, deterministic) +} +func (dst *Link) XXX_Merge(src proto.Message) { + xxx_messageInfo_Link.Merge(dst, src) +} +func (m *Link) XXX_Size() int { + return xxx_messageInfo_Link.Size(m) +} +func (m *Link) XXX_DiscardUnknown() { + xxx_messageInfo_Link.DiscardUnknown(m) +} + +var xxx_messageInfo_Link proto.InternalMessageInfo + +func (m *Link) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +type Fault struct { + Subject FaultSubject `protobuf:"varint,1,opt,name=subject,proto3,enum=ctrl.pb.FaultSubject" json:"subject,omitempty"` + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Fault) Reset() { *m = Fault{} } +func (m *Fault) String() string { return proto.CompactTextString(m) } +func (*Fault) ProtoMessage() {} +func (*Fault) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{5} +} +func (m *Fault) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Fault.Unmarshal(m, b) +} +func (m *Fault) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Fault.Marshal(b, m, deterministic) +} +func (dst *Fault) XXX_Merge(src proto.Message) { + xxx_messageInfo_Fault.Merge(dst, src) +} +func (m *Fault) XXX_Size() int { + return xxx_messageInfo_Fault.Size(m) +} +func (m *Fault) XXX_DiscardUnknown() { + xxx_messageInfo_Fault.DiscardUnknown(m) +} + +var xxx_messageInfo_Fault proto.InternalMessageInfo + +func (m *Fault) GetSubject() FaultSubject { + if m != nil { + return m.Subject + } + return FaultSubject_IngressFault +} + +func (m *Fault) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +type Route struct { + SessionId string `protobuf:"bytes,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Egress *Route_Egress `protobuf:"bytes,2,opt,name=egress,proto3" json:"egress,omitempty"` + Forwards []*Route_Forward `protobuf:"bytes,3,rep,name=forwards,proto3" json:"forwards,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Route) Reset() { *m = Route{} } +func (m *Route) String() string { return proto.CompactTextString(m) } +func (*Route) ProtoMessage() {} +func (*Route) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{6} +} +func (m *Route) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Route.Unmarshal(m, b) +} +func (m *Route) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Route.Marshal(b, m, deterministic) +} +func (dst *Route) XXX_Merge(src proto.Message) { + xxx_messageInfo_Route.Merge(dst, src) +} +func (m *Route) XXX_Size() int { + return xxx_messageInfo_Route.Size(m) +} +func (m *Route) XXX_DiscardUnknown() { + xxx_messageInfo_Route.DiscardUnknown(m) +} + +var xxx_messageInfo_Route proto.InternalMessageInfo + +func (m *Route) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *Route) GetEgress() *Route_Egress { + if m != nil { + return m.Egress + } + return nil +} + +func (m *Route) GetForwards() []*Route_Forward { + if m != nil { + return m.Forwards + } + return nil +} + +type Route_Egress struct { + Binding string `protobuf:"bytes,1,opt,name=binding,proto3" json:"binding,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + Destination string `protobuf:"bytes,3,opt,name=destination,proto3" json:"destination,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Route_Egress) Reset() { *m = Route_Egress{} } +func (m *Route_Egress) String() string { return proto.CompactTextString(m) } +func (*Route_Egress) ProtoMessage() {} +func (*Route_Egress) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{6, 0} +} +func (m *Route_Egress) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Route_Egress.Unmarshal(m, b) +} +func (m *Route_Egress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Route_Egress.Marshal(b, m, deterministic) +} +func (dst *Route_Egress) XXX_Merge(src proto.Message) { + xxx_messageInfo_Route_Egress.Merge(dst, src) +} +func (m *Route_Egress) XXX_Size() int { + return xxx_messageInfo_Route_Egress.Size(m) +} +func (m *Route_Egress) XXX_DiscardUnknown() { + xxx_messageInfo_Route_Egress.DiscardUnknown(m) +} + +var xxx_messageInfo_Route_Egress proto.InternalMessageInfo + +func (m *Route_Egress) GetBinding() string { + if m != nil { + return m.Binding + } + return "" +} + +func (m *Route_Egress) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *Route_Egress) GetDestination() string { + if m != nil { + return m.Destination + } + return "" +} + +type Route_Forward struct { + SrcAddress string `protobuf:"bytes,1,opt,name=srcAddress,proto3" json:"srcAddress,omitempty"` + DstAddress string `protobuf:"bytes,2,opt,name=dstAddress,proto3" json:"dstAddress,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Route_Forward) Reset() { *m = Route_Forward{} } +func (m *Route_Forward) String() string { return proto.CompactTextString(m) } +func (*Route_Forward) ProtoMessage() {} +func (*Route_Forward) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{6, 1} +} +func (m *Route_Forward) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Route_Forward.Unmarshal(m, b) +} +func (m *Route_Forward) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Route_Forward.Marshal(b, m, deterministic) +} +func (dst *Route_Forward) XXX_Merge(src proto.Message) { + xxx_messageInfo_Route_Forward.Merge(dst, src) +} +func (m *Route_Forward) XXX_Size() int { + return xxx_messageInfo_Route_Forward.Size(m) +} +func (m *Route_Forward) XXX_DiscardUnknown() { + xxx_messageInfo_Route_Forward.DiscardUnknown(m) +} + +var xxx_messageInfo_Route_Forward proto.InternalMessageInfo + +func (m *Route_Forward) GetSrcAddress() string { + if m != nil { + return m.SrcAddress + } + return "" +} + +func (m *Route_Forward) GetDstAddress() string { + if m != nil { + return m.DstAddress + } + return "" +} + +type Unroute struct { + SessionId string `protobuf:"bytes,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Now bool `protobuf:"varint,2,opt,name=now,proto3" json:"now,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Unroute) Reset() { *m = Unroute{} } +func (m *Unroute) String() string { return proto.CompactTextString(m) } +func (*Unroute) ProtoMessage() {} +func (*Unroute) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{7} +} +func (m *Unroute) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Unroute.Unmarshal(m, b) +} +func (m *Unroute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Unroute.Marshal(b, m, deterministic) +} +func (dst *Unroute) XXX_Merge(src proto.Message) { + xxx_messageInfo_Unroute.Merge(dst, src) +} +func (m *Unroute) XXX_Size() int { + return xxx_messageInfo_Unroute.Size(m) +} +func (m *Unroute) XXX_DiscardUnknown() { + xxx_messageInfo_Unroute.DiscardUnknown(m) +} + +var xxx_messageInfo_Unroute proto.InternalMessageInfo + +func (m *Unroute) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *Unroute) GetNow() bool { + if m != nil { + return m.Now + } + return false +} + +type MetricsMessage struct { + SourceType MetricsSourceType `protobuf:"varint,1,opt,name=sourceType,proto3,enum=ctrl.pb.MetricsSourceType" json:"sourceType,omitempty"` + SourceId string `protobuf:"bytes,2,opt,name=sourceId,proto3" json:"sourceId,omitempty"` + Timestamp *timestamp.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Tags map[string]string `protobuf:"bytes,4,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + IntValues map[string]int64 `protobuf:"bytes,5,rep,name=intValues,proto3" json:"intValues,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + FloatValues map[string]float64 `protobuf:"bytes,6,rep,name=floatValues,proto3" json:"floatValues,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"` + Meters map[string]*MetricsMessage_Meter `protobuf:"bytes,7,rep,name=meters,proto3" json:"meters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Histograms map[string]*MetricsMessage_Histogram `protobuf:"bytes,8,rep,name=histograms,proto3" json:"histograms,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + IntervalCounters map[string]*MetricsMessage_IntervalCounter `protobuf:"bytes,9,rep,name=intervalCounters,proto3" json:"intervalCounters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricsMessage) Reset() { *m = MetricsMessage{} } +func (m *MetricsMessage) String() string { return proto.CompactTextString(m) } +func (*MetricsMessage) ProtoMessage() {} +func (*MetricsMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{8} +} +func (m *MetricsMessage) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricsMessage.Unmarshal(m, b) +} +func (m *MetricsMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricsMessage.Marshal(b, m, deterministic) +} +func (dst *MetricsMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricsMessage.Merge(dst, src) +} +func (m *MetricsMessage) XXX_Size() int { + return xxx_messageInfo_MetricsMessage.Size(m) +} +func (m *MetricsMessage) XXX_DiscardUnknown() { + xxx_messageInfo_MetricsMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricsMessage proto.InternalMessageInfo + +func (m *MetricsMessage) GetSourceType() MetricsSourceType { + if m != nil { + return m.SourceType + } + return MetricsSourceType_Ingress +} + +func (m *MetricsMessage) GetSourceId() string { + if m != nil { + return m.SourceId + } + return "" +} + +func (m *MetricsMessage) GetTimestamp() *timestamp.Timestamp { + if m != nil { + return m.Timestamp + } + return nil +} + +func (m *MetricsMessage) GetTags() map[string]string { + if m != nil { + return m.Tags + } + return nil +} + +func (m *MetricsMessage) GetIntValues() map[string]int64 { + if m != nil { + return m.IntValues + } + return nil +} + +func (m *MetricsMessage) GetFloatValues() map[string]float64 { + if m != nil { + return m.FloatValues + } + return nil +} + +func (m *MetricsMessage) GetMeters() map[string]*MetricsMessage_Meter { + if m != nil { + return m.Meters + } + return nil +} + +func (m *MetricsMessage) GetHistograms() map[string]*MetricsMessage_Histogram { + if m != nil { + return m.Histograms + } + return nil +} + +func (m *MetricsMessage) GetIntervalCounters() map[string]*MetricsMessage_IntervalCounter { + if m != nil { + return m.IntervalCounters + } + return nil +} + +type MetricsMessage_Meter struct { + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + M1Rate float64 `protobuf:"fixed64,2,opt,name=m1Rate,proto3" json:"m1Rate,omitempty"` + M5Rate float64 `protobuf:"fixed64,3,opt,name=m5Rate,proto3" json:"m5Rate,omitempty"` + M15Rate float64 `protobuf:"fixed64,4,opt,name=m15Rate,proto3" json:"m15Rate,omitempty"` + MeanRate float64 `protobuf:"fixed64,5,opt,name=meanRate,proto3" json:"meanRate,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricsMessage_Meter) Reset() { *m = MetricsMessage_Meter{} } +func (m *MetricsMessage_Meter) String() string { return proto.CompactTextString(m) } +func (*MetricsMessage_Meter) ProtoMessage() {} +func (*MetricsMessage_Meter) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{8, 6} +} +func (m *MetricsMessage_Meter) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricsMessage_Meter.Unmarshal(m, b) +} +func (m *MetricsMessage_Meter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricsMessage_Meter.Marshal(b, m, deterministic) +} +func (dst *MetricsMessage_Meter) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricsMessage_Meter.Merge(dst, src) +} +func (m *MetricsMessage_Meter) XXX_Size() int { + return xxx_messageInfo_MetricsMessage_Meter.Size(m) +} +func (m *MetricsMessage_Meter) XXX_DiscardUnknown() { + xxx_messageInfo_MetricsMessage_Meter.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricsMessage_Meter proto.InternalMessageInfo + +func (m *MetricsMessage_Meter) GetCount() int64 { + if m != nil { + return m.Count + } + return 0 +} + +func (m *MetricsMessage_Meter) GetM1Rate() float64 { + if m != nil { + return m.M1Rate + } + return 0 +} + +func (m *MetricsMessage_Meter) GetM5Rate() float64 { + if m != nil { + return m.M5Rate + } + return 0 +} + +func (m *MetricsMessage_Meter) GetM15Rate() float64 { + if m != nil { + return m.M15Rate + } + return 0 +} + +func (m *MetricsMessage_Meter) GetMeanRate() float64 { + if m != nil { + return m.MeanRate + } + return 0 +} + +type MetricsMessage_Histogram struct { + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` + Max int64 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty"` + Mean float64 `protobuf:"fixed64,3,opt,name=mean,proto3" json:"mean,omitempty"` + Min int64 `protobuf:"varint,4,opt,name=min,proto3" json:"min,omitempty"` + StdDev float64 `protobuf:"fixed64,5,opt,name=stdDev,proto3" json:"stdDev,omitempty"` + Variance float64 `protobuf:"fixed64,6,opt,name=variance,proto3" json:"variance,omitempty"` + P50 float64 `protobuf:"fixed64,7,opt,name=p50,proto3" json:"p50,omitempty"` + P75 float64 `protobuf:"fixed64,8,opt,name=p75,proto3" json:"p75,omitempty"` + P95 float64 `protobuf:"fixed64,9,opt,name=p95,proto3" json:"p95,omitempty"` + P99 float64 `protobuf:"fixed64,10,opt,name=p99,proto3" json:"p99,omitempty"` + P999 float64 `protobuf:"fixed64,11,opt,name=p999,proto3" json:"p999,omitempty"` + P9999 float64 `protobuf:"fixed64,12,opt,name=p9999,proto3" json:"p9999,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricsMessage_Histogram) Reset() { *m = MetricsMessage_Histogram{} } +func (m *MetricsMessage_Histogram) String() string { return proto.CompactTextString(m) } +func (*MetricsMessage_Histogram) ProtoMessage() {} +func (*MetricsMessage_Histogram) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{8, 7} +} +func (m *MetricsMessage_Histogram) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricsMessage_Histogram.Unmarshal(m, b) +} +func (m *MetricsMessage_Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricsMessage_Histogram.Marshal(b, m, deterministic) +} +func (dst *MetricsMessage_Histogram) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricsMessage_Histogram.Merge(dst, src) +} +func (m *MetricsMessage_Histogram) XXX_Size() int { + return xxx_messageInfo_MetricsMessage_Histogram.Size(m) +} +func (m *MetricsMessage_Histogram) XXX_DiscardUnknown() { + xxx_messageInfo_MetricsMessage_Histogram.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricsMessage_Histogram proto.InternalMessageInfo + +func (m *MetricsMessage_Histogram) GetCount() int64 { + if m != nil { + return m.Count + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetMax() int64 { + if m != nil { + return m.Max + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetMean() float64 { + if m != nil { + return m.Mean + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetMin() int64 { + if m != nil { + return m.Min + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetStdDev() float64 { + if m != nil { + return m.StdDev + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetVariance() float64 { + if m != nil { + return m.Variance + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP50() float64 { + if m != nil { + return m.P50 + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP75() float64 { + if m != nil { + return m.P75 + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP95() float64 { + if m != nil { + return m.P95 + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP99() float64 { + if m != nil { + return m.P99 + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP999() float64 { + if m != nil { + return m.P999 + } + return 0 +} + +func (m *MetricsMessage_Histogram) GetP9999() float64 { + if m != nil { + return m.P9999 + } + return 0 +} + +type MetricsMessage_IntervalCounter struct { + IntervalLength uint64 `protobuf:"varint,1,opt,name=intervalLength,proto3" json:"intervalLength,omitempty"` + Buckets []*MetricsMessage_IntervalBucket `protobuf:"bytes,2,rep,name=buckets,proto3" json:"buckets,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricsMessage_IntervalCounter) Reset() { *m = MetricsMessage_IntervalCounter{} } +func (m *MetricsMessage_IntervalCounter) String() string { return proto.CompactTextString(m) } +func (*MetricsMessage_IntervalCounter) ProtoMessage() {} +func (*MetricsMessage_IntervalCounter) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{8, 8} +} +func (m *MetricsMessage_IntervalCounter) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricsMessage_IntervalCounter.Unmarshal(m, b) +} +func (m *MetricsMessage_IntervalCounter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricsMessage_IntervalCounter.Marshal(b, m, deterministic) +} +func (dst *MetricsMessage_IntervalCounter) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricsMessage_IntervalCounter.Merge(dst, src) +} +func (m *MetricsMessage_IntervalCounter) XXX_Size() int { + return xxx_messageInfo_MetricsMessage_IntervalCounter.Size(m) +} +func (m *MetricsMessage_IntervalCounter) XXX_DiscardUnknown() { + xxx_messageInfo_MetricsMessage_IntervalCounter.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricsMessage_IntervalCounter proto.InternalMessageInfo + +func (m *MetricsMessage_IntervalCounter) GetIntervalLength() uint64 { + if m != nil { + return m.IntervalLength + } + return 0 +} + +func (m *MetricsMessage_IntervalCounter) GetBuckets() []*MetricsMessage_IntervalBucket { + if m != nil { + return m.Buckets + } + return nil +} + +type MetricsMessage_IntervalBucket struct { + IntervalStartUTC int64 `protobuf:"varint,1,opt,name=intervalStartUTC,proto3" json:"intervalStartUTC,omitempty"` + Values map[string]uint64 `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricsMessage_IntervalBucket) Reset() { *m = MetricsMessage_IntervalBucket{} } +func (m *MetricsMessage_IntervalBucket) String() string { return proto.CompactTextString(m) } +func (*MetricsMessage_IntervalBucket) ProtoMessage() {} +func (*MetricsMessage_IntervalBucket) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{8, 9} +} +func (m *MetricsMessage_IntervalBucket) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricsMessage_IntervalBucket.Unmarshal(m, b) +} +func (m *MetricsMessage_IntervalBucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricsMessage_IntervalBucket.Marshal(b, m, deterministic) +} +func (dst *MetricsMessage_IntervalBucket) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricsMessage_IntervalBucket.Merge(dst, src) +} +func (m *MetricsMessage_IntervalBucket) XXX_Size() int { + return xxx_messageInfo_MetricsMessage_IntervalBucket.Size(m) +} +func (m *MetricsMessage_IntervalBucket) XXX_DiscardUnknown() { + xxx_messageInfo_MetricsMessage_IntervalBucket.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricsMessage_IntervalBucket proto.InternalMessageInfo + +func (m *MetricsMessage_IntervalBucket) GetIntervalStartUTC() int64 { + if m != nil { + return m.IntervalStartUTC + } + return 0 +} + +func (m *MetricsMessage_IntervalBucket) GetValues() map[string]uint64 { + if m != nil { + return m.Values + } + return nil +} + +type InspectRequest struct { + RequestedValues []string `protobuf:"bytes,1,rep,name=requestedValues,proto3" json:"requestedValues,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectRequest) Reset() { *m = InspectRequest{} } +func (m *InspectRequest) String() string { return proto.CompactTextString(m) } +func (*InspectRequest) ProtoMessage() {} +func (*InspectRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{9} +} +func (m *InspectRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectRequest.Unmarshal(m, b) +} +func (m *InspectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectRequest.Marshal(b, m, deterministic) +} +func (dst *InspectRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectRequest.Merge(dst, src) +} +func (m *InspectRequest) XXX_Size() int { + return xxx_messageInfo_InspectRequest.Size(m) +} +func (m *InspectRequest) XXX_DiscardUnknown() { + xxx_messageInfo_InspectRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectRequest proto.InternalMessageInfo + +func (m *InspectRequest) GetRequestedValues() []string { + if m != nil { + return m.RequestedValues + } + return nil +} + +type InspectResponse struct { + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Errors []string `protobuf:"bytes,2,rep,name=errors,proto3" json:"errors,omitempty"` + Values []*InspectResponse_InspectValue `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectResponse) Reset() { *m = InspectResponse{} } +func (m *InspectResponse) String() string { return proto.CompactTextString(m) } +func (*InspectResponse) ProtoMessage() {} +func (*InspectResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{10} +} +func (m *InspectResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectResponse.Unmarshal(m, b) +} +func (m *InspectResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectResponse.Marshal(b, m, deterministic) +} +func (dst *InspectResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectResponse.Merge(dst, src) +} +func (m *InspectResponse) XXX_Size() int { + return xxx_messageInfo_InspectResponse.Size(m) +} +func (m *InspectResponse) XXX_DiscardUnknown() { + xxx_messageInfo_InspectResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectResponse proto.InternalMessageInfo + +func (m *InspectResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *InspectResponse) GetErrors() []string { + if m != nil { + return m.Errors + } + return nil +} + +func (m *InspectResponse) GetValues() []*InspectResponse_InspectValue { + if m != nil { + return m.Values + } + return nil +} + +type InspectResponse_InspectValue struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectResponse_InspectValue) Reset() { *m = InspectResponse_InspectValue{} } +func (m *InspectResponse_InspectValue) String() string { return proto.CompactTextString(m) } +func (*InspectResponse_InspectValue) ProtoMessage() {} +func (*InspectResponse_InspectValue) Descriptor() ([]byte, []int) { + return fileDescriptor_ctrl_fd5a7f82fe7b28d6, []int{10, 0} +} +func (m *InspectResponse_InspectValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectResponse_InspectValue.Unmarshal(m, b) +} +func (m *InspectResponse_InspectValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectResponse_InspectValue.Marshal(b, m, deterministic) +} +func (dst *InspectResponse_InspectValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectResponse_InspectValue.Merge(dst, src) +} +func (m *InspectResponse_InspectValue) XXX_Size() int { + return xxx_messageInfo_InspectResponse_InspectValue.Size(m) +} +func (m *InspectResponse_InspectValue) XXX_DiscardUnknown() { + xxx_messageInfo_InspectResponse_InspectValue.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectResponse_InspectValue proto.InternalMessageInfo + +func (m *InspectResponse_InspectValue) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *InspectResponse_InspectValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +func init() { + proto.RegisterType((*SessionRequest)(nil), "ctrl.pb.SessionRequest") + proto.RegisterType((*BindRequest)(nil), "ctrl.pb.BindRequest") + proto.RegisterType((*BindResponse)(nil), "ctrl.pb.BindResponse") + proto.RegisterType((*Dial)(nil), "ctrl.pb.Dial") + proto.RegisterType((*Link)(nil), "ctrl.pb.Link") + proto.RegisterType((*Fault)(nil), "ctrl.pb.Fault") + proto.RegisterType((*Route)(nil), "ctrl.pb.Route") + proto.RegisterType((*Route_Egress)(nil), "ctrl.pb.Route.Egress") + proto.RegisterType((*Route_Forward)(nil), "ctrl.pb.Route.Forward") + proto.RegisterType((*Unroute)(nil), "ctrl.pb.Unroute") + proto.RegisterType((*MetricsMessage)(nil), "ctrl.pb.MetricsMessage") + proto.RegisterMapType((map[string]float64)(nil), "ctrl.pb.MetricsMessage.FloatValuesEntry") + proto.RegisterMapType((map[string]*MetricsMessage_Histogram)(nil), "ctrl.pb.MetricsMessage.HistogramsEntry") + proto.RegisterMapType((map[string]int64)(nil), "ctrl.pb.MetricsMessage.IntValuesEntry") + proto.RegisterMapType((map[string]*MetricsMessage_IntervalCounter)(nil), "ctrl.pb.MetricsMessage.IntervalCountersEntry") + proto.RegisterMapType((map[string]*MetricsMessage_Meter)(nil), "ctrl.pb.MetricsMessage.MetersEntry") + proto.RegisterMapType((map[string]string)(nil), "ctrl.pb.MetricsMessage.TagsEntry") + proto.RegisterType((*MetricsMessage_Meter)(nil), "ctrl.pb.MetricsMessage.Meter") + proto.RegisterType((*MetricsMessage_Histogram)(nil), "ctrl.pb.MetricsMessage.Histogram") + proto.RegisterType((*MetricsMessage_IntervalCounter)(nil), "ctrl.pb.MetricsMessage.IntervalCounter") + proto.RegisterType((*MetricsMessage_IntervalBucket)(nil), "ctrl.pb.MetricsMessage.IntervalBucket") + proto.RegisterMapType((map[string]uint64)(nil), "ctrl.pb.MetricsMessage.IntervalBucket.ValuesEntry") + proto.RegisterType((*InspectRequest)(nil), "ctrl.pb.InspectRequest") + proto.RegisterType((*InspectResponse)(nil), "ctrl.pb.InspectResponse") + proto.RegisterType((*InspectResponse_InspectValue)(nil), "ctrl.pb.InspectResponse.InspectValue") + proto.RegisterEnum("ctrl.pb.ContentType", ContentType_name, ContentType_value) + proto.RegisterEnum("ctrl.pb.BindType", BindType_name, BindType_value) + proto.RegisterEnum("ctrl.pb.FaultSubject", FaultSubject_name, FaultSubject_value) + proto.RegisterEnum("ctrl.pb.MetricsSourceType", MetricsSourceType_name, MetricsSourceType_value) +} + +func init() { proto.RegisterFile("ctrl.proto", fileDescriptor_ctrl_fd5a7f82fe7b28d6) } + +var fileDescriptor_ctrl_fd5a7f82fe7b28d6 = []byte{ + // 1310 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x56, 0x5b, 0x6f, 0x1a, 0xc7, + 0x17, 0xff, 0x83, 0x81, 0x85, 0xb3, 0x0e, 0x26, 0x93, 0xbf, 0x5d, 0x44, 0x6f, 0x0e, 0x55, 0x13, + 0xcb, 0x52, 0x70, 0xe2, 0x08, 0xd9, 0xb8, 0x17, 0x25, 0xbe, 0x35, 0xae, 0x6c, 0xa9, 0x5a, 0xe3, + 0x2a, 0xed, 0x43, 0xd5, 0x35, 0x8c, 0xc9, 0xd6, 0xb0, 0x4b, 0x77, 0x07, 0x52, 0xab, 0x8f, 0xfd, + 0x48, 0x7d, 0xed, 0x5b, 0xbf, 0x4c, 0xef, 0x8d, 0x7a, 0xcd, 0x5b, 0x7b, 0xe6, 0xcc, 0xec, 0x32, + 0x60, 0x13, 0xbb, 0x4f, 0x3b, 0xe7, 0xf6, 0x3b, 0xd7, 0x99, 0x3d, 0x00, 0x2d, 0x11, 0x76, 0x6b, + 0xfd, 0x30, 0x10, 0x01, 0xb3, 0xd4, 0xf9, 0xb8, 0xf2, 0x7a, 0x27, 0x08, 0x3a, 0x5d, 0xbe, 0x42, + 0xec, 0xe3, 0xc1, 0xc9, 0x8a, 0xf0, 0x7a, 0x3c, 0x12, 0x6e, 0xaf, 0xaf, 0x34, 0xab, 0xfb, 0x50, + 0x3c, 0xe4, 0x51, 0xe4, 0x05, 0xbe, 0xc3, 0x3f, 0x1f, 0xa0, 0x88, 0xbd, 0x02, 0x05, 0xcf, 0xef, + 0x84, 0xc8, 0xdc, 0x6b, 0x97, 0x53, 0x8b, 0xa9, 0xa5, 0x82, 0x33, 0x62, 0x48, 0x69, 0xc4, 0xc3, + 0xa1, 0xd7, 0xe2, 0x28, 0x4d, 0x2b, 0x69, 0xc2, 0xa8, 0xf6, 0xc1, 0xde, 0xf4, 0xfc, 0x76, 0x0c, + 0x75, 0x07, 0xf2, 0xc7, 0x48, 0x36, 0xcf, 0xfa, 0x9c, 0x90, 0x8a, 0xab, 0xd7, 0x6b, 0x3a, 0xb2, + 0xda, 0xa6, 0x16, 0x38, 0x89, 0x0a, 0xfb, 0x3f, 0x64, 0x45, 0x70, 0xca, 0x7d, 0x8d, 0xab, 0x88, + 0x71, 0x8f, 0x33, 0x93, 0x1e, 0x37, 0x61, 0x56, 0x79, 0x8c, 0xfa, 0x81, 0x1f, 0x71, 0x56, 0x06, + 0x2b, 0x1a, 0xb4, 0x5a, 0x18, 0x2c, 0x79, 0xcc, 0x3b, 0x31, 0x29, 0x25, 0x98, 0x7a, 0xe4, 0x76, + 0xb8, 0xc6, 0x8f, 0xc9, 0xea, 0x5d, 0xc8, 0x6c, 0x7b, 0x6e, 0x97, 0x15, 0x21, 0xed, 0xc5, 0x29, + 0xe3, 0x49, 0x5a, 0xb8, 0xed, 0xb6, 0x4c, 0x3c, 0xb6, 0xd0, 0x64, 0x75, 0x01, 0x32, 0xfb, 0x9e, + 0x7f, 0x3a, 0x69, 0x51, 0x7d, 0x04, 0xd9, 0x5d, 0x77, 0xd0, 0x15, 0x6c, 0x45, 0x86, 0x71, 0xfc, + 0x19, 0x6f, 0x09, 0x9d, 0xf8, 0x7c, 0x92, 0x38, 0x29, 0x1c, 0x2a, 0xa1, 0x13, 0x6b, 0x69, 0xa4, + 0x74, 0x82, 0xf4, 0x75, 0x1a, 0xb2, 0x4e, 0x30, 0x10, 0x5c, 0xe5, 0x4f, 0x1d, 0x1a, 0xf5, 0x23, + 0x61, 0x60, 0x89, 0x73, 0xbc, 0x93, 0x84, 0x68, 0x1b, 0x7e, 0xc8, 0xba, 0xb6, 0x43, 0x42, 0x47, + 0x2b, 0xb1, 0x55, 0xc8, 0x9f, 0x04, 0xe1, 0x53, 0x37, 0x6c, 0x47, 0x58, 0xcb, 0x19, 0x34, 0x58, + 0x98, 0x30, 0xd8, 0x55, 0x62, 0x27, 0xd1, 0xab, 0x7c, 0x02, 0x39, 0x85, 0x22, 0x0b, 0x22, 0x9b, + 0x85, 0xd3, 0xa0, 0x03, 0x89, 0xc9, 0xe9, 0xa5, 0x62, 0x8b, 0x60, 0xb7, 0x71, 0x16, 0x3c, 0xdf, + 0x15, 0x18, 0xb1, 0x6e, 0xa0, 0xc9, 0xaa, 0xec, 0x81, 0xa5, 0x9d, 0xb2, 0xd7, 0x00, 0xa2, 0xb0, + 0xf5, 0x50, 0x23, 0x29, 0x1f, 0x06, 0x47, 0xca, 0xdb, 0x91, 0x78, 0x38, 0xe6, 0xc9, 0xe0, 0x54, + 0x1b, 0x60, 0x1d, 0xf9, 0xe1, 0x15, 0xca, 0x56, 0x82, 0x19, 0x3f, 0x78, 0x4a, 0x08, 0x79, 0x47, + 0x1e, 0xab, 0xcf, 0xaf, 0x41, 0xf1, 0x80, 0x8b, 0xd0, 0x6b, 0x45, 0x07, 0x6a, 0x2e, 0xd8, 0x06, + 0x46, 0x13, 0x0c, 0xc2, 0x16, 0x37, 0x06, 0xb8, 0x92, 0x94, 0x4b, 0x2b, 0x1f, 0x26, 0x1a, 0x8e, + 0xa1, 0xcd, 0x2a, 0x90, 0x57, 0x54, 0x72, 0x4d, 0x12, 0x9a, 0xad, 0x43, 0x21, 0xb9, 0x86, 0x54, + 0x10, 0x1b, 0x61, 0xd5, 0x45, 0xad, 0xc5, 0x17, 0xb5, 0xd6, 0x8c, 0x35, 0x9c, 0x91, 0x32, 0xab, + 0x43, 0x46, 0xb8, 0x9d, 0xa8, 0x9c, 0xa1, 0xd6, 0xdd, 0x9c, 0x8c, 0x45, 0x07, 0x5e, 0x6b, 0xa2, + 0xce, 0x8e, 0x2f, 0xc2, 0x33, 0x87, 0xd4, 0xd9, 0xb6, 0xbc, 0xd2, 0xe2, 0x43, 0xb7, 0x8b, 0xb7, + 0xb2, 0x9c, 0x25, 0xdb, 0x5b, 0xd3, 0x6c, 0xf7, 0x62, 0x45, 0x05, 0x30, 0x32, 0x64, 0xef, 0x83, + 0x7d, 0xd2, 0x0d, 0xdc, 0x18, 0x27, 0x47, 0x38, 0x4b, 0xd3, 0x70, 0x76, 0x47, 0xaa, 0x0a, 0xc9, + 0x34, 0x66, 0x6f, 0x41, 0xae, 0xc7, 0x05, 0x0f, 0xa3, 0xb2, 0x45, 0x30, 0x6f, 0x4c, 0x83, 0x39, + 0x20, 0x2d, 0x85, 0xa0, 0x4d, 0xd8, 0x7b, 0x00, 0x4f, 0xbc, 0x48, 0x04, 0x9d, 0xd0, 0xed, 0x45, + 0xe5, 0x3c, 0x01, 0xdc, 0x9e, 0x06, 0xf0, 0x28, 0xd1, 0x54, 0x20, 0x86, 0x29, 0xfb, 0x08, 0x4a, + 0x98, 0x1e, 0xbe, 0x25, 0x6e, 0x77, 0x2b, 0x18, 0xf8, 0x14, 0x4f, 0x81, 0xe0, 0xee, 0xbc, 0xa0, + 0x3c, 0x63, 0xfa, 0x0a, 0xf4, 0x1c, 0x4c, 0x65, 0x0d, 0x0a, 0x49, 0x17, 0xe4, 0xb4, 0x9d, 0xf2, + 0x33, 0x3d, 0x85, 0xf2, 0x28, 0x9f, 0xba, 0xa1, 0xac, 0x44, 0xfc, 0xd4, 0x11, 0xb1, 0x91, 0x5e, + 0x4f, 0x55, 0xde, 0x86, 0xe2, 0x78, 0x0b, 0x2e, 0xb3, 0x9e, 0x31, 0xad, 0xdf, 0x85, 0xd2, 0x64, + 0xe1, 0x2f, 0xb3, 0x4f, 0x99, 0xf6, 0x8f, 0xc1, 0x36, 0x2a, 0x7e, 0x81, 0xe9, 0x7d, 0xd3, 0xd4, + 0x5e, 0x7d, 0xf5, 0x85, 0x7d, 0x33, 0x91, 0x3f, 0x85, 0xb9, 0x89, 0x56, 0x5c, 0x80, 0xbe, 0x36, + 0x8e, 0x7e, 0xf3, 0xd2, 0xa6, 0x9a, 0x1e, 0xba, 0x30, 0x7f, 0x61, 0x77, 0x2e, 0xf0, 0xf3, 0xce, + 0xb8, 0x9f, 0xdb, 0x57, 0xec, 0xb6, 0xe9, 0xed, 0xab, 0x14, 0x64, 0x29, 0x49, 0x59, 0xcd, 0x96, + 0x94, 0x93, 0x03, 0xec, 0x06, 0x11, 0x6c, 0x01, 0x27, 0xfc, 0x9e, 0xe3, 0x8a, 0xb8, 0xc8, 0x9a, + 0x22, 0x7e, 0x9d, 0xf8, 0x33, 0x9a, 0x4f, 0x14, 0xfd, 0x9e, 0xee, 0x29, 0x41, 0x86, 0x04, 0x31, + 0x29, 0x9f, 0x92, 0x1e, 0x77, 0x7d, 0x12, 0x65, 0x49, 0x94, 0xd0, 0x95, 0x7f, 0x52, 0x50, 0x48, + 0x8a, 0x31, 0x25, 0x12, 0x4c, 0xbf, 0xe7, 0x7e, 0xa1, 0x67, 0x45, 0x1e, 0x19, 0x83, 0x8c, 0x44, + 0xd0, 0x11, 0xd0, 0x99, 0xb4, 0x3c, 0x9f, 0x7c, 0x4b, 0x2d, 0xcf, 0x97, 0x91, 0x46, 0xa2, 0xbd, + 0xcd, 0x87, 0xda, 0xab, 0xa6, 0x64, 0x3c, 0x43, 0x37, 0xf4, 0x5c, 0xbf, 0xc5, 0xf1, 0x11, 0xa0, + 0x78, 0x62, 0x5a, 0xa2, 0xf4, 0xeb, 0x77, 0xf1, 0x52, 0x4b, 0xb6, 0x3c, 0x12, 0x67, 0xad, 0x8e, + 0xb7, 0x54, 0x71, 0xd6, 0xea, 0xc4, 0x69, 0xd4, 0xf1, 0xa2, 0x29, 0x4e, 0x43, 0x73, 0x1a, 0x65, + 0x88, 0x39, 0x0d, 0x19, 0x21, 0x7e, 0x1a, 0x65, 0x5b, 0x45, 0x28, 0xcf, 0x32, 0x3b, 0xf9, 0x6d, + 0x94, 0x67, 0xd5, 0xd4, 0x12, 0x51, 0xf9, 0x12, 0xe6, 0x26, 0xba, 0xc4, 0x6e, 0x41, 0x31, 0xbe, + 0x8f, 0xfb, 0xdc, 0xef, 0x88, 0x27, 0x54, 0x8f, 0x8c, 0x33, 0xc1, 0x65, 0x0f, 0xf0, 0x77, 0x36, + 0x68, 0x9d, 0x72, 0x21, 0x7f, 0x25, 0x97, 0x3d, 0x8a, 0x64, 0xb8, 0x49, 0xea, 0x4e, 0x6c, 0x56, + 0xf9, 0x36, 0x45, 0xb7, 0xd5, 0x90, 0xb1, 0xe5, 0xd1, 0x9b, 0x72, 0x28, 0xdc, 0x50, 0x1c, 0x35, + 0xb7, 0x74, 0x3b, 0xce, 0xf1, 0xf1, 0x45, 0xcd, 0x0d, 0xd5, 0x63, 0xaa, 0xfe, 0xc5, 0xab, 0x57, + 0xf3, 0x5f, 0x33, 0x9f, 0x55, 0x8d, 0x50, 0x69, 0x80, 0xfd, 0x1f, 0x2e, 0x7d, 0xc6, 0x18, 0xe5, + 0xea, 0x86, 0x4c, 0x22, 0xea, 0xcb, 0x7d, 0x44, 0x2f, 0x6e, 0x4b, 0x30, 0x17, 0xaa, 0x23, 0x6f, + 0xeb, 0xe7, 0x3e, 0x85, 0x11, 0x16, 0x9c, 0x49, 0x76, 0xf5, 0x9b, 0x94, 0xac, 0xbf, 0x36, 0xbe, + 0x74, 0x07, 0xc3, 0x91, 0xe2, 0x61, 0x18, 0x84, 0xaa, 0xe0, 0x05, 0x47, 0x53, 0x78, 0x1f, 0xc7, + 0x0b, 0xf1, 0x66, 0x52, 0x88, 0x09, 0xec, 0x98, 0x26, 0xef, 0x49, 0xee, 0xeb, 0x30, 0x6b, 0xf2, + 0xe5, 0xf4, 0xf8, 0x6e, 0x8f, 0xeb, 0xec, 0xe9, 0x7c, 0xf1, 0x8b, 0xbb, 0xfc, 0x2c, 0x0d, 0xf6, + 0x56, 0x80, 0xd5, 0xf5, 0x05, 0xfd, 0xb6, 0xf3, 0x90, 0xf9, 0x98, 0x87, 0x41, 0xe9, 0x7f, 0xec, + 0x25, 0x60, 0xe3, 0x8b, 0xb1, 0x94, 0x97, 0xbe, 0xb3, 0x0c, 0xc1, 0xa1, 0xca, 0x8a, 0x04, 0xdf, + 0x5b, 0xec, 0x1a, 0xe4, 0xe5, 0x1a, 0x49, 0xe4, 0x0f, 0x44, 0xca, 0x1d, 0x91, 0xc8, 0x1f, 0x2d, + 0x5c, 0xf0, 0x0a, 0xb4, 0xf9, 0x11, 0xfd, 0x13, 0xd1, 0xb4, 0x70, 0x11, 0xfd, 0xb3, 0x85, 0x0d, + 0xb3, 0xf5, 0xea, 0x42, 0x9c, 0x5f, 0x88, 0xa3, 0xc7, 0x80, 0x38, 0xbf, 0x5a, 0xb8, 0x4b, 0xbd, + 0xdc, 0x0c, 0x3a, 0xb8, 0x26, 0x7c, 0xe0, 0xf5, 0x79, 0x33, 0x74, 0xd1, 0xbb, 0x19, 0xdc, 0x33, + 0x8b, 0xdd, 0x80, 0x22, 0xf1, 0x77, 0x86, 0x3a, 0xa3, 0xd2, 0x6f, 0x16, 0xa6, 0x3e, 0x67, 0x6c, + 0xe5, 0xc4, 0xfd, 0xdd, 0x62, 0xf3, 0x50, 0x32, 0x37, 0x67, 0x62, 0xff, 0x41, 0xe9, 0x8d, 0x0f, + 0x03, 0x09, 0xfe, 0xb4, 0xb0, 0xab, 0x37, 0x26, 0x9a, 0x41, 0x92, 0xbf, 0x08, 0x9f, 0x46, 0xfa, + 0x31, 0x6d, 0x89, 0xc4, 0xfd, 0xdb, 0xc2, 0x5e, 0x5f, 0xd7, 0x75, 0xda, 0x75, 0xbd, 0x2e, 0xa7, + 0x15, 0xbf, 0xf4, 0xdc, 0x5a, 0x5e, 0x84, 0x7c, 0xbc, 0xfb, 0xcb, 0x72, 0xcb, 0x33, 0x96, 0x1b, + 0x20, 0x77, 0xe4, 0xcb, 0x6d, 0xb2, 0x94, 0x5a, 0x7e, 0x00, 0xb3, 0xe6, 0x92, 0x8c, 0x85, 0xc0, + 0xf6, 0x12, 0x36, 0xb1, 0x51, 0x7b, 0x0e, 0xec, 0x1d, 0x83, 0x91, 0xc2, 0x62, 0x17, 0x64, 0xb1, + 0x15, 0x99, 0x5e, 0xde, 0x80, 0xeb, 0xe7, 0xd6, 0x33, 0x66, 0x83, 0xa5, 0x61, 0x94, 0x3f, 0x85, + 0x80, 0xc6, 0xb3, 0x90, 0xa7, 0x0b, 0xe6, 0xbb, 0xdd, 0x52, 0xfa, 0x38, 0x47, 0x2b, 0xd8, 0xfd, + 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x13, 0xf3, 0x77, 0x5a, 0x50, 0x0d, 0x00, 0x00, +} diff --git a/fabric/pb/ctrl_pb/ctrl.proto b/fabric/pb/ctrl_pb/ctrl.proto new file mode 100644 index 000000000..5c4aa3781 --- /dev/null +++ b/fabric/pb/ctrl_pb/ctrl.proto @@ -0,0 +1,156 @@ +syntax = "proto3"; + +package ctrl.pb; + +import "google/protobuf/timestamp.proto"; + +enum ContentType { + Zero = 0; + + SessionRequestType = 1000; + SessionSuccessType = 1001; + DialType = 1002; + LinkType = 1003; + FaultType = 1004; + RouteType = 1005; + UnrouteType = 1006; + MetricsType = 1007; + TogglePipeTracesRequestType = 1008; + TraceEventType = 1010; + BindRequestType = 1011; + BindResponseType = 1012; + InspectRequestType = 1013; + InspectResponseType = 1014; + StartXgressType = 1015; + SessionFailedType = 1016; +} + +message SessionRequest { + string ingressId = 1; + string serviceId = 2; +} + +enum BindType { + Bind = 0; + Unbind = 1; +} + +message BindRequest { + BindType bindType = 1; + string token = 2; + string serviceId = 3; +} + +message BindResponse { + bool success = 1; + string message = 2; +} + +message Dial { + string id = 1; + string address = 2; +} + +message Link { + string id = 1; +} + +enum FaultSubject { + IngressFault = 0; + EgressFault = 1; + LinkFault = 2; +} + +message Fault { + FaultSubject subject = 1; + string id = 2; +} + +message Route { + string sessionId = 1; + + message Egress { + string binding = 1; + string address = 2; + string destination = 3; + } + Egress egress = 2; + + message Forward { + string srcAddress = 1; + string dstAddress = 2; + } + repeated Forward forwards = 3; +} + +message Unroute { + string sessionId = 1; + bool now = 2; +} + +enum MetricsSourceType { + Ingress = 0; + Egress = 1; + Internal = 2; // Is there a better word here? Router, Intermediary, NonEdge? + // Do we also want Edge and/or SDK here? Anything else? +} + +message MetricsMessage { + MetricsSourceType sourceType = 1; + string sourceId = 2; + google.protobuf.Timestamp timestamp = 3; + map tags = 4; + map intValues = 5; + map floatValues = 6; + map meters = 7; + map histograms = 8; + map intervalCounters = 9; + + message Meter { + int64 count = 1; + double m1Rate = 2; + double m5Rate = 3; + double m15Rate = 4; + double meanRate = 5; + } + + message Histogram { + int64 count = 1; + int64 max = 2; + double mean = 3; + int64 min = 4; + double stdDev = 5; + double variance = 6; + double p50 = 7; + double p75 = 8; + double p95 = 9; + double p99 = 10; + double p999 = 11; + double p9999 = 12; + } + + message IntervalCounter { + uint64 intervalLength = 1; + repeated IntervalBucket buckets = 2; + } + + message IntervalBucket { + int64 intervalStartUTC = 1; // Only need minute resolution, this will be seconds resolution + map values = 3; + } +} + +message InspectRequest { + repeated string requestedValues = 1; +} + +message InspectResponse { + bool success = 1; + repeated string errors = 2; + repeated InspectValue values = 3; + + message InspectValue { + string name = 1; + string value = 2; + } +} \ No newline at end of file diff --git a/fabric/pb/ctrl_pb/decoder.go b/fabric/pb/ctrl_pb/decoder.go new file mode 100644 index 000000000..f8355bf49 --- /dev/null +++ b/fabric/pb/ctrl_pb/decoder.go @@ -0,0 +1,230 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package ctrl_pb + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/ctrl_msg" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "strconv" +) + +type Decoder struct{} + +const DECODER = "ctrl" + +func (d Decoder) Decode(msg *channel2.Message) ([]byte, bool) { + switch msg.ContentType { + case int32(ContentType_SessionRequestType): + sessionRequest := &SessionRequest{} + if err := proto.Unmarshal(msg.Body, sessionRequest); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Session Request") + meta["ingressId"] = sessionRequest.IngressId + meta["serviceId"] = sessionRequest.ServiceId + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_SessionSuccessType): + meta := channel2.NewTraceMessageDecode(DECODER, "Session Success Response") + meta["sessionId"] = string(msg.Body) + meta["address"] = string(msg.Headers[ctrl_msg.SessionSuccessAddressHeader]) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + case int32(ContentType_SessionFailedType): + meta := channel2.NewTraceMessageDecode(DECODER, "Session Failed Response") + message := string(msg.Body) + if message != "" { + meta["message"] = message + } + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + case int32(ContentType_DialType): + connect := &Dial{} + if err := proto.Unmarshal(msg.Body, connect); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Dial") + meta["id"] = connect.Id + meta["address"] = connect.Address + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_LinkType): + link := &Link{} + if err := proto.Unmarshal(msg.Body, link); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Link") + meta["id"] = link.Id + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_FaultType): + fault := &Fault{} + if err := proto.Unmarshal(msg.Body, fault); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Fault") + meta["subject"] = fault.Subject.String() + meta["id"] = fault.Id + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_RouteType): + route := &Route{} + if err := proto.Unmarshal(msg.Body, route); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Route") + meta["sessionId"] = route.SessionId + if route.Egress != nil { + meta["egress.address"] = route.Egress.Address + meta["egress.destination"] = route.Egress.Destination + } + for i, forward := range route.Forwards { + meta[fmt.Sprintf("forward[%d].srcAddress", i)] = forward.SrcAddress + meta[fmt.Sprintf("forward[%d].dstAddress", i)] = forward.DstAddress + } + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_UnrouteType): + unroute := &Unroute{} + if err := proto.Unmarshal(msg.Body, unroute); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Unroute") + meta["sessionId"] = unroute.SessionId + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + } + + case int32(ContentType_StartXgressType): + meta := channel2.NewTraceMessageDecode(DECODER, "Start Xgress") + meta["sessionId"] = string(msg.Body) + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + return data, true + + case int32(ContentType_MetricsType): + metricsMsg := &MetricsMessage{} + if err := proto.Unmarshal(msg.Body, metricsMsg); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Metrics") + + for name, metric := range metricsMsg.Histograms { + meta[name+".min"] = metric.Min + meta[name+".mean"] = metric.Mean + meta[name+".max"] = metric.Max + meta[name+".p95"] = metric.P95 + meta[name+".p99"] = metric.P99 + } + + for name, metric := range metricsMsg.Meters { + meta[name+".count"] = metric.Count + meta[name+".meanRate"] = metric.MeanRate + meta[name+".m1Rate"] = metric.M1Rate + meta[name+".m5Rate"] = metric.M5Rate + meta[name+".m15Rate"] = metric.M15Rate + } + + for name, counter := range metricsMsg.IntervalCounters { + for _, bucket := range counter.Buckets { + for key, val := range bucket.Values { + meta[name+"."+key+"["+strconv.FormatInt(bucket.IntervalStartUTC, 10)+"]"] = val + } + } + } + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + } + + } + + return nil, false +} diff --git a/fabric/pb/ctrl_pb/inspect.go b/fabric/pb/ctrl_pb/inspect.go new file mode 100644 index 000000000..1e4ac28dd --- /dev/null +++ b/fabric/pb/ctrl_pb/inspect.go @@ -0,0 +1,33 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package ctrl_pb + +func (request *InspectRequest) GetContentType() int32 { + return int32(ContentType_InspectRequestType) +} + +func (response *InspectResponse) GetContentType() int32 { + return int32(ContentType_InspectResponseType) +} + +func (response *InspectResponse) AddValue(name, value string) { + newValue := &InspectResponse_InspectValue{ + Name: name, + Value: value, + } + response.Values = append(response.Values, newValue) +} diff --git a/fabric/pb/mgmt_pb/decoder.go b/fabric/pb/mgmt_pb/decoder.go new file mode 100644 index 000000000..002bfa212 --- /dev/null +++ b/fabric/pb/mgmt_pb/decoder.go @@ -0,0 +1,323 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package mgmt_pb + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type Decoder struct{} + +const DECODER = "mgmt" + +func (d Decoder) Decode(msg *channel2.Message) ([]byte, bool) { + switch msg.ContentType { + case int32(ContentType_ListServicesRequestType): + data, err := channel2.NewTraceMessageDecode(DECODER, "List Services Request").MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + case int32(ContentType_ListServicesResponseType): + listServices := &ListServicesResponse{} + if err := proto.Unmarshal(msg.Body, listServices); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "List Services Response") + meta["services"] = len(listServices.Services) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_CreateServiceRequestType): + createService := &CreateServiceRequest{} + if err := proto.Unmarshal(msg.Body, createService); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Create Service Request") + meta["service"] = serviceToString(createService.Service) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_RemoveServiceRequestType): + removeService := &RemoveServiceRequest{} + if err := proto.Unmarshal(msg.Body, removeService); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Remove Service Request") + meta["serviceId"] = removeService.ServiceId + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_GetServiceRequestType): + getService := &GetServiceRequest{} + if err := proto.Unmarshal(msg.Body, getService); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Get Service Request") + meta["serviceId"] = getService.ServiceId + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_GetServiceResponseType): + getService := &GetServiceResponse{} + if err := proto.Unmarshal(msg.Body, getService); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Get Service Response") + meta["service"] = serviceToString(getService.Service) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_ListRoutersRequestType): + data, err := channel2.NewTraceMessageDecode(DECODER, "List Routers Request").MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + case int32(ContentType_ListRoutersResponseType): + listRouters := &ListRoutersResponse{} + if err := proto.Unmarshal(msg.Body, listRouters); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "List Routers Response") + meta["routers"] = len(listRouters.Routers) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_CreateRouterRequestType): + createRouter := &CreateRouterRequest{} + if err := proto.Unmarshal(msg.Body, createRouter); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Create Router Request") + meta["router"] = routerToString(createRouter.Router) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_RemoveRouterRequestType): + removeRouter := &RemoveRouterRequest{} + if err := proto.Unmarshal(msg.Body, removeRouter); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Remove Router Request") + meta["routerId"] = removeRouter.RouterId + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_ListLinksRequestType): + data, err := channel2.NewTraceMessageDecode(DECODER, "List Links Request").MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + case int32(ContentType_ListLinksResponseType): + listLinks := &ListLinksResponse{} + if err := proto.Unmarshal(msg.Body, listLinks); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "List Links Response") + meta["links"] = len(listLinks.Links) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_SetLinkCostRequestType): + setLinkCost := &SetLinkCostRequest{} + if err := proto.Unmarshal(msg.Body, setLinkCost); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Set Link Cost Request") + meta["linkId"] = setLinkCost.LinkId + meta["cost"] = setLinkCost.Cost + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_SetLinkDownRequestType): + setLinkDown := &SetLinkDownRequest{} + if err := proto.Unmarshal(msg.Body, setLinkDown); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Set Link Down Request") + meta["linkId"] = setLinkDown.LinkId + meta["down"] = setLinkDown.Down + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + case int32(ContentType_ListSessionsRequestType): + data, err := channel2.NewTraceMessageDecode(DECODER, "List Sessions Request").MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + case int32(ContentType_ListSessionsResponseType): + listSessions := &ListSessionsResponse{} + if err := proto.Unmarshal(msg.Body, listSessions); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "List Sessions Response") + meta["sessions"] = len(listSessions.Sessions) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + return nil, true + } + } + + return nil, false +} + +func serviceToString(service *Service) string { + return fmt.Sprintf("{id=[%s] binding=[%s] endpoint=[%s] egress=[%s]}", service.Id, service.Binding, service.EndpointAddress, service.Egress) +} + +func routerToString(router *Router) string { + return fmt.Sprintf("{id=[%s] fingerprint=[%s] listener=[%s] connected=[%t]}", router.Id, router.Fingerprint, router.ListenerAddress, router.Connected) +} + +func (circuit *Circuit) CalculateDisplayPath() string { + if circuit == nil { + return "" + } + out := "" + for i := 0; i < len(circuit.Path); i++ { + if i < len(circuit.Links) { + out += fmt.Sprintf("[r/%s]->{l/%s}->", circuit.Path[i], circuit.Links[i]) + } else { + out += fmt.Sprintf("[r/%s]\n", circuit.Path[i]) + } + } + return out +} \ No newline at end of file diff --git a/fabric/pb/mgmt_pb/mgmt.pb.go b/fabric/pb/mgmt_pb/mgmt.pb.go new file mode 100644 index 000000000..5b1b09c31 --- /dev/null +++ b/fabric/pb/mgmt_pb/mgmt.pb.go @@ -0,0 +1,1892 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: mgmt.proto + +package mgmt_pb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import timestamp "github.com/golang/protobuf/ptypes/timestamp" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type ContentType int32 + +const ( + // Protoc says this has to be here + ContentType_Zero ContentType = 0 + // Services + ContentType_ListServicesRequestType ContentType = 10001 + ContentType_ListServicesResponseType ContentType = 10002 + ContentType_CreateServiceRequestType ContentType = 10003 + ContentType_RemoveServiceRequestType ContentType = 10005 + ContentType_GetServiceRequestType ContentType = 10006 + ContentType_GetServiceResponseType ContentType = 10007 + // Routers + ContentType_ListRoutersRequestType ContentType = 10010 + ContentType_ListRoutersResponseType ContentType = 10011 + ContentType_CreateRouterRequestType ContentType = 10012 + ContentType_RemoveRouterRequestType ContentType = 10013 + // Links + ContentType_ListLinksRequestType ContentType = 10020 + ContentType_ListLinksResponseType ContentType = 10021 + ContentType_SetLinkCostRequestType ContentType = 10022 + ContentType_SetLinkDownRequestType ContentType = 10023 + // Sessions + ContentType_ListSessionsRequestType ContentType = 10030 + ContentType_ListSessionsResponseType ContentType = 10031 + ContentType_RemoveSessionRequestType ContentType = 10032 + // Streams + ContentType_StreamMetricsRequestType ContentType = 10040 + ContentType_StreamMetricsEventType ContentType = 10041 + ContentType_StreamSessionsRequestType ContentType = 10042 + ContentType_StreamSessionsEventType ContentType = 10043 + ContentType_TogglePipeTracesRequestType ContentType = 10044 + ContentType_ToggleSessionTracesRequestType ContentType = 10045 + ContentType_StreamTracesRequestType ContentType = 10046 + ContentType_StreamTracesEventType ContentType = 10047 + // Inspect + ContentType_InspectRequestType ContentType = 10048 + ContentType_InspectResponseType ContentType = 10049 +) + +var ContentType_name = map[int32]string{ + 0: "Zero", + 10001: "ListServicesRequestType", + 10002: "ListServicesResponseType", + 10003: "CreateServiceRequestType", + 10005: "RemoveServiceRequestType", + 10006: "GetServiceRequestType", + 10007: "GetServiceResponseType", + 10010: "ListRoutersRequestType", + 10011: "ListRoutersResponseType", + 10012: "CreateRouterRequestType", + 10013: "RemoveRouterRequestType", + 10020: "ListLinksRequestType", + 10021: "ListLinksResponseType", + 10022: "SetLinkCostRequestType", + 10023: "SetLinkDownRequestType", + 10030: "ListSessionsRequestType", + 10031: "ListSessionsResponseType", + 10032: "RemoveSessionRequestType", + 10040: "StreamMetricsRequestType", + 10041: "StreamMetricsEventType", + 10042: "StreamSessionsRequestType", + 10043: "StreamSessionsEventType", + 10044: "TogglePipeTracesRequestType", + 10045: "ToggleSessionTracesRequestType", + 10046: "StreamTracesRequestType", + 10047: "StreamTracesEventType", + 10048: "InspectRequestType", + 10049: "InspectResponseType", +} +var ContentType_value = map[string]int32{ + "Zero": 0, + "ListServicesRequestType": 10001, + "ListServicesResponseType": 10002, + "CreateServiceRequestType": 10003, + "RemoveServiceRequestType": 10005, + "GetServiceRequestType": 10006, + "GetServiceResponseType": 10007, + "ListRoutersRequestType": 10010, + "ListRoutersResponseType": 10011, + "CreateRouterRequestType": 10012, + "RemoveRouterRequestType": 10013, + "ListLinksRequestType": 10020, + "ListLinksResponseType": 10021, + "SetLinkCostRequestType": 10022, + "SetLinkDownRequestType": 10023, + "ListSessionsRequestType": 10030, + "ListSessionsResponseType": 10031, + "RemoveSessionRequestType": 10032, + "StreamMetricsRequestType": 10040, + "StreamMetricsEventType": 10041, + "StreamSessionsRequestType": 10042, + "StreamSessionsEventType": 10043, + "TogglePipeTracesRequestType": 10044, + "ToggleSessionTracesRequestType": 10045, + "StreamTracesRequestType": 10046, + "StreamTracesEventType": 10047, + "InspectRequestType": 10048, + "InspectResponseType": 10049, +} + +func (x ContentType) String() string { + return proto.EnumName(ContentType_name, int32(x)) +} +func (ContentType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{0} +} + +type StreamSessionEventType int32 + +const ( + StreamSessionEventType_SessionCreated StreamSessionEventType = 0 + StreamSessionEventType_SessionDeleted StreamSessionEventType = 1 + StreamSessionEventType_SessionPresent StreamSessionEventType = 2 + StreamSessionEventType_CircuitUpdated StreamSessionEventType = 3 +) + +var StreamSessionEventType_name = map[int32]string{ + 0: "SessionCreated", + 1: "SessionDeleted", + 2: "SessionPresent", + 3: "CircuitUpdated", +} +var StreamSessionEventType_value = map[string]int32{ + "SessionCreated": 0, + "SessionDeleted": 1, + "SessionPresent": 2, + "CircuitUpdated": 3, +} + +func (x StreamSessionEventType) String() string { + return proto.EnumName(StreamSessionEventType_name, int32(x)) +} +func (StreamSessionEventType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{1} +} + +type TraceFilterType int32 + +const ( + TraceFilterType_EXCLUDE TraceFilterType = 0 + TraceFilterType_INCLUDE TraceFilterType = 1 +) + +var TraceFilterType_name = map[int32]string{ + 0: "EXCLUDE", + 1: "INCLUDE", +} +var TraceFilterType_value = map[string]int32{ + "EXCLUDE": 0, + "INCLUDE": 1, +} + +func (x TraceFilterType) String() string { + return proto.EnumName(TraceFilterType_name, int32(x)) +} +func (TraceFilterType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{2} +} + +type Service struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Binding string `protobuf:"bytes,2,opt,name=binding,proto3" json:"binding,omitempty"` + EndpointAddress string `protobuf:"bytes,3,opt,name=endpointAddress,proto3" json:"endpointAddress,omitempty"` + Egress string `protobuf:"bytes,4,opt,name=egress,proto3" json:"egress,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Service) Reset() { *m = Service{} } +func (m *Service) String() string { return proto.CompactTextString(m) } +func (*Service) ProtoMessage() {} +func (*Service) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{0} +} +func (m *Service) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Service.Unmarshal(m, b) +} +func (m *Service) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Service.Marshal(b, m, deterministic) +} +func (dst *Service) XXX_Merge(src proto.Message) { + xxx_messageInfo_Service.Merge(dst, src) +} +func (m *Service) XXX_Size() int { + return xxx_messageInfo_Service.Size(m) +} +func (m *Service) XXX_DiscardUnknown() { + xxx_messageInfo_Service.DiscardUnknown(m) +} + +var xxx_messageInfo_Service proto.InternalMessageInfo + +func (m *Service) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Service) GetBinding() string { + if m != nil { + return m.Binding + } + return "" +} + +func (m *Service) GetEndpointAddress() string { + if m != nil { + return m.EndpointAddress + } + return "" +} + +func (m *Service) GetEgress() string { + if m != nil { + return m.Egress + } + return "" +} + +type ListServicesRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListServicesRequest) Reset() { *m = ListServicesRequest{} } +func (m *ListServicesRequest) String() string { return proto.CompactTextString(m) } +func (*ListServicesRequest) ProtoMessage() {} +func (*ListServicesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{1} +} +func (m *ListServicesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListServicesRequest.Unmarshal(m, b) +} +func (m *ListServicesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListServicesRequest.Marshal(b, m, deterministic) +} +func (dst *ListServicesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListServicesRequest.Merge(dst, src) +} +func (m *ListServicesRequest) XXX_Size() int { + return xxx_messageInfo_ListServicesRequest.Size(m) +} +func (m *ListServicesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListServicesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListServicesRequest proto.InternalMessageInfo + +type ListServicesResponse struct { + Services []*Service `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListServicesResponse) Reset() { *m = ListServicesResponse{} } +func (m *ListServicesResponse) String() string { return proto.CompactTextString(m) } +func (*ListServicesResponse) ProtoMessage() {} +func (*ListServicesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{2} +} +func (m *ListServicesResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListServicesResponse.Unmarshal(m, b) +} +func (m *ListServicesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListServicesResponse.Marshal(b, m, deterministic) +} +func (dst *ListServicesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListServicesResponse.Merge(dst, src) +} +func (m *ListServicesResponse) XXX_Size() int { + return xxx_messageInfo_ListServicesResponse.Size(m) +} +func (m *ListServicesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListServicesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListServicesResponse proto.InternalMessageInfo + +func (m *ListServicesResponse) GetServices() []*Service { + if m != nil { + return m.Services + } + return nil +} + +type CreateServiceRequest struct { + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateServiceRequest) Reset() { *m = CreateServiceRequest{} } +func (m *CreateServiceRequest) String() string { return proto.CompactTextString(m) } +func (*CreateServiceRequest) ProtoMessage() {} +func (*CreateServiceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{3} +} +func (m *CreateServiceRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateServiceRequest.Unmarshal(m, b) +} +func (m *CreateServiceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateServiceRequest.Marshal(b, m, deterministic) +} +func (dst *CreateServiceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateServiceRequest.Merge(dst, src) +} +func (m *CreateServiceRequest) XXX_Size() int { + return xxx_messageInfo_CreateServiceRequest.Size(m) +} +func (m *CreateServiceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CreateServiceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateServiceRequest proto.InternalMessageInfo + +func (m *CreateServiceRequest) GetService() *Service { + if m != nil { + return m.Service + } + return nil +} + +type RemoveServiceRequest struct { + ServiceId string `protobuf:"bytes,1,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RemoveServiceRequest) Reset() { *m = RemoveServiceRequest{} } +func (m *RemoveServiceRequest) String() string { return proto.CompactTextString(m) } +func (*RemoveServiceRequest) ProtoMessage() {} +func (*RemoveServiceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{4} +} +func (m *RemoveServiceRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RemoveServiceRequest.Unmarshal(m, b) +} +func (m *RemoveServiceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RemoveServiceRequest.Marshal(b, m, deterministic) +} +func (dst *RemoveServiceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoveServiceRequest.Merge(dst, src) +} +func (m *RemoveServiceRequest) XXX_Size() int { + return xxx_messageInfo_RemoveServiceRequest.Size(m) +} +func (m *RemoveServiceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_RemoveServiceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_RemoveServiceRequest proto.InternalMessageInfo + +func (m *RemoveServiceRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +type GetServiceRequest struct { + ServiceId string `protobuf:"bytes,1,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetServiceRequest) Reset() { *m = GetServiceRequest{} } +func (m *GetServiceRequest) String() string { return proto.CompactTextString(m) } +func (*GetServiceRequest) ProtoMessage() {} +func (*GetServiceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{5} +} +func (m *GetServiceRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetServiceRequest.Unmarshal(m, b) +} +func (m *GetServiceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetServiceRequest.Marshal(b, m, deterministic) +} +func (dst *GetServiceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetServiceRequest.Merge(dst, src) +} +func (m *GetServiceRequest) XXX_Size() int { + return xxx_messageInfo_GetServiceRequest.Size(m) +} +func (m *GetServiceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetServiceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetServiceRequest proto.InternalMessageInfo + +func (m *GetServiceRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +type GetServiceResponse struct { + Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetServiceResponse) Reset() { *m = GetServiceResponse{} } +func (m *GetServiceResponse) String() string { return proto.CompactTextString(m) } +func (*GetServiceResponse) ProtoMessage() {} +func (*GetServiceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{6} +} +func (m *GetServiceResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetServiceResponse.Unmarshal(m, b) +} +func (m *GetServiceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetServiceResponse.Marshal(b, m, deterministic) +} +func (dst *GetServiceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetServiceResponse.Merge(dst, src) +} +func (m *GetServiceResponse) XXX_Size() int { + return xxx_messageInfo_GetServiceResponse.Size(m) +} +func (m *GetServiceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetServiceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetServiceResponse proto.InternalMessageInfo + +func (m *GetServiceResponse) GetService() *Service { + if m != nil { + return m.Service + } + return nil +} + +type Router struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Fingerprint string `protobuf:"bytes,2,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` + ListenerAddress string `protobuf:"bytes,3,opt,name=listenerAddress,proto3" json:"listenerAddress,omitempty"` + Connected bool `protobuf:"varint,4,opt,name=connected,proto3" json:"connected,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Router) Reset() { *m = Router{} } +func (m *Router) String() string { return proto.CompactTextString(m) } +func (*Router) ProtoMessage() {} +func (*Router) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{7} +} +func (m *Router) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Router.Unmarshal(m, b) +} +func (m *Router) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Router.Marshal(b, m, deterministic) +} +func (dst *Router) XXX_Merge(src proto.Message) { + xxx_messageInfo_Router.Merge(dst, src) +} +func (m *Router) XXX_Size() int { + return xxx_messageInfo_Router.Size(m) +} +func (m *Router) XXX_DiscardUnknown() { + xxx_messageInfo_Router.DiscardUnknown(m) +} + +var xxx_messageInfo_Router proto.InternalMessageInfo + +func (m *Router) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Router) GetFingerprint() string { + if m != nil { + return m.Fingerprint + } + return "" +} + +func (m *Router) GetListenerAddress() string { + if m != nil { + return m.ListenerAddress + } + return "" +} + +func (m *Router) GetConnected() bool { + if m != nil { + return m.Connected + } + return false +} + +type ListRoutersRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListRoutersRequest) Reset() { *m = ListRoutersRequest{} } +func (m *ListRoutersRequest) String() string { return proto.CompactTextString(m) } +func (*ListRoutersRequest) ProtoMessage() {} +func (*ListRoutersRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{8} +} +func (m *ListRoutersRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListRoutersRequest.Unmarshal(m, b) +} +func (m *ListRoutersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListRoutersRequest.Marshal(b, m, deterministic) +} +func (dst *ListRoutersRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListRoutersRequest.Merge(dst, src) +} +func (m *ListRoutersRequest) XXX_Size() int { + return xxx_messageInfo_ListRoutersRequest.Size(m) +} +func (m *ListRoutersRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListRoutersRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListRoutersRequest proto.InternalMessageInfo + +type ListRoutersResponse struct { + Routers []*Router `protobuf:"bytes,1,rep,name=routers,proto3" json:"routers,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListRoutersResponse) Reset() { *m = ListRoutersResponse{} } +func (m *ListRoutersResponse) String() string { return proto.CompactTextString(m) } +func (*ListRoutersResponse) ProtoMessage() {} +func (*ListRoutersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{9} +} +func (m *ListRoutersResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListRoutersResponse.Unmarshal(m, b) +} +func (m *ListRoutersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListRoutersResponse.Marshal(b, m, deterministic) +} +func (dst *ListRoutersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListRoutersResponse.Merge(dst, src) +} +func (m *ListRoutersResponse) XXX_Size() int { + return xxx_messageInfo_ListRoutersResponse.Size(m) +} +func (m *ListRoutersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListRoutersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListRoutersResponse proto.InternalMessageInfo + +func (m *ListRoutersResponse) GetRouters() []*Router { + if m != nil { + return m.Routers + } + return nil +} + +type CreateRouterRequest struct { + Router *Router `protobuf:"bytes,1,opt,name=router,proto3" json:"router,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CreateRouterRequest) Reset() { *m = CreateRouterRequest{} } +func (m *CreateRouterRequest) String() string { return proto.CompactTextString(m) } +func (*CreateRouterRequest) ProtoMessage() {} +func (*CreateRouterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{10} +} +func (m *CreateRouterRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CreateRouterRequest.Unmarshal(m, b) +} +func (m *CreateRouterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CreateRouterRequest.Marshal(b, m, deterministic) +} +func (dst *CreateRouterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CreateRouterRequest.Merge(dst, src) +} +func (m *CreateRouterRequest) XXX_Size() int { + return xxx_messageInfo_CreateRouterRequest.Size(m) +} +func (m *CreateRouterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CreateRouterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CreateRouterRequest proto.InternalMessageInfo + +func (m *CreateRouterRequest) GetRouter() *Router { + if m != nil { + return m.Router + } + return nil +} + +type RemoveRouterRequest struct { + RouterId string `protobuf:"bytes,1,opt,name=routerId,proto3" json:"routerId,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RemoveRouterRequest) Reset() { *m = RemoveRouterRequest{} } +func (m *RemoveRouterRequest) String() string { return proto.CompactTextString(m) } +func (*RemoveRouterRequest) ProtoMessage() {} +func (*RemoveRouterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{11} +} +func (m *RemoveRouterRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RemoveRouterRequest.Unmarshal(m, b) +} +func (m *RemoveRouterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RemoveRouterRequest.Marshal(b, m, deterministic) +} +func (dst *RemoveRouterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoveRouterRequest.Merge(dst, src) +} +func (m *RemoveRouterRequest) XXX_Size() int { + return xxx_messageInfo_RemoveRouterRequest.Size(m) +} +func (m *RemoveRouterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_RemoveRouterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_RemoveRouterRequest proto.InternalMessageInfo + +func (m *RemoveRouterRequest) GetRouterId() string { + if m != nil { + return m.RouterId + } + return "" +} + +type Link struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Src string `protobuf:"bytes,2,opt,name=src,proto3" json:"src,omitempty"` + Dst string `protobuf:"bytes,3,opt,name=dst,proto3" json:"dst,omitempty"` + State string `protobuf:"bytes,4,opt,name=state,proto3" json:"state,omitempty"` + Down bool `protobuf:"varint,5,opt,name=down,proto3" json:"down,omitempty"` + Cost int32 `protobuf:"varint,6,opt,name=cost,proto3" json:"cost,omitempty"` + SrcLatency int64 `protobuf:"varint,7,opt,name=srcLatency,proto3" json:"srcLatency,omitempty"` + DstLatency int64 `protobuf:"varint,8,opt,name=dstLatency,proto3" json:"dstLatency,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Link) Reset() { *m = Link{} } +func (m *Link) String() string { return proto.CompactTextString(m) } +func (*Link) ProtoMessage() {} +func (*Link) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{12} +} +func (m *Link) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Link.Unmarshal(m, b) +} +func (m *Link) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Link.Marshal(b, m, deterministic) +} +func (dst *Link) XXX_Merge(src proto.Message) { + xxx_messageInfo_Link.Merge(dst, src) +} +func (m *Link) XXX_Size() int { + return xxx_messageInfo_Link.Size(m) +} +func (m *Link) XXX_DiscardUnknown() { + xxx_messageInfo_Link.DiscardUnknown(m) +} + +var xxx_messageInfo_Link proto.InternalMessageInfo + +func (m *Link) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Link) GetSrc() string { + if m != nil { + return m.Src + } + return "" +} + +func (m *Link) GetDst() string { + if m != nil { + return m.Dst + } + return "" +} + +func (m *Link) GetState() string { + if m != nil { + return m.State + } + return "" +} + +func (m *Link) GetDown() bool { + if m != nil { + return m.Down + } + return false +} + +func (m *Link) GetCost() int32 { + if m != nil { + return m.Cost + } + return 0 +} + +func (m *Link) GetSrcLatency() int64 { + if m != nil { + return m.SrcLatency + } + return 0 +} + +func (m *Link) GetDstLatency() int64 { + if m != nil { + return m.DstLatency + } + return 0 +} + +type ListLinksRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListLinksRequest) Reset() { *m = ListLinksRequest{} } +func (m *ListLinksRequest) String() string { return proto.CompactTextString(m) } +func (*ListLinksRequest) ProtoMessage() {} +func (*ListLinksRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{13} +} +func (m *ListLinksRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListLinksRequest.Unmarshal(m, b) +} +func (m *ListLinksRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListLinksRequest.Marshal(b, m, deterministic) +} +func (dst *ListLinksRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListLinksRequest.Merge(dst, src) +} +func (m *ListLinksRequest) XXX_Size() int { + return xxx_messageInfo_ListLinksRequest.Size(m) +} +func (m *ListLinksRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListLinksRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListLinksRequest proto.InternalMessageInfo + +type ListLinksResponse struct { + Links []*Link `protobuf:"bytes,1,rep,name=links,proto3" json:"links,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListLinksResponse) Reset() { *m = ListLinksResponse{} } +func (m *ListLinksResponse) String() string { return proto.CompactTextString(m) } +func (*ListLinksResponse) ProtoMessage() {} +func (*ListLinksResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{14} +} +func (m *ListLinksResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListLinksResponse.Unmarshal(m, b) +} +func (m *ListLinksResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListLinksResponse.Marshal(b, m, deterministic) +} +func (dst *ListLinksResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListLinksResponse.Merge(dst, src) +} +func (m *ListLinksResponse) XXX_Size() int { + return xxx_messageInfo_ListLinksResponse.Size(m) +} +func (m *ListLinksResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListLinksResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListLinksResponse proto.InternalMessageInfo + +func (m *ListLinksResponse) GetLinks() []*Link { + if m != nil { + return m.Links + } + return nil +} + +type SetLinkCostRequest struct { + LinkId string `protobuf:"bytes,1,opt,name=linkId,proto3" json:"linkId,omitempty"` + Cost int32 `protobuf:"varint,2,opt,name=cost,proto3" json:"cost,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SetLinkCostRequest) Reset() { *m = SetLinkCostRequest{} } +func (m *SetLinkCostRequest) String() string { return proto.CompactTextString(m) } +func (*SetLinkCostRequest) ProtoMessage() {} +func (*SetLinkCostRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{15} +} +func (m *SetLinkCostRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SetLinkCostRequest.Unmarshal(m, b) +} +func (m *SetLinkCostRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SetLinkCostRequest.Marshal(b, m, deterministic) +} +func (dst *SetLinkCostRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetLinkCostRequest.Merge(dst, src) +} +func (m *SetLinkCostRequest) XXX_Size() int { + return xxx_messageInfo_SetLinkCostRequest.Size(m) +} +func (m *SetLinkCostRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetLinkCostRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetLinkCostRequest proto.InternalMessageInfo + +func (m *SetLinkCostRequest) GetLinkId() string { + if m != nil { + return m.LinkId + } + return "" +} + +func (m *SetLinkCostRequest) GetCost() int32 { + if m != nil { + return m.Cost + } + return 0 +} + +type SetLinkDownRequest struct { + LinkId string `protobuf:"bytes,1,opt,name=linkId,proto3" json:"linkId,omitempty"` + Down bool `protobuf:"varint,2,opt,name=down,proto3" json:"down,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SetLinkDownRequest) Reset() { *m = SetLinkDownRequest{} } +func (m *SetLinkDownRequest) String() string { return proto.CompactTextString(m) } +func (*SetLinkDownRequest) ProtoMessage() {} +func (*SetLinkDownRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{16} +} +func (m *SetLinkDownRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_SetLinkDownRequest.Unmarshal(m, b) +} +func (m *SetLinkDownRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_SetLinkDownRequest.Marshal(b, m, deterministic) +} +func (dst *SetLinkDownRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetLinkDownRequest.Merge(dst, src) +} +func (m *SetLinkDownRequest) XXX_Size() int { + return xxx_messageInfo_SetLinkDownRequest.Size(m) +} +func (m *SetLinkDownRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetLinkDownRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetLinkDownRequest proto.InternalMessageInfo + +func (m *SetLinkDownRequest) GetLinkId() string { + if m != nil { + return m.LinkId + } + return "" +} + +func (m *SetLinkDownRequest) GetDown() bool { + if m != nil { + return m.Down + } + return false +} + +type Circuit struct { + Path []string `protobuf:"bytes,1,rep,name=path,proto3" json:"path,omitempty"` + Links []string `protobuf:"bytes,2,rep,name=links,proto3" json:"links,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Circuit) Reset() { *m = Circuit{} } +func (m *Circuit) String() string { return proto.CompactTextString(m) } +func (*Circuit) ProtoMessage() {} +func (*Circuit) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{17} +} +func (m *Circuit) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Circuit.Unmarshal(m, b) +} +func (m *Circuit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Circuit.Marshal(b, m, deterministic) +} +func (dst *Circuit) XXX_Merge(src proto.Message) { + xxx_messageInfo_Circuit.Merge(dst, src) +} +func (m *Circuit) XXX_Size() int { + return xxx_messageInfo_Circuit.Size(m) +} +func (m *Circuit) XXX_DiscardUnknown() { + xxx_messageInfo_Circuit.DiscardUnknown(m) +} + +var xxx_messageInfo_Circuit proto.InternalMessageInfo + +func (m *Circuit) GetPath() []string { + if m != nil { + return m.Path + } + return nil +} + +func (m *Circuit) GetLinks() []string { + if m != nil { + return m.Links + } + return nil +} + +type Session struct { + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + ClientId string `protobuf:"bytes,2,opt,name=clientId,proto3" json:"clientId,omitempty"` + ServiceId string `protobuf:"bytes,3,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + Circuit *Circuit `protobuf:"bytes,4,opt,name=circuit,proto3" json:"circuit,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Session) Reset() { *m = Session{} } +func (m *Session) String() string { return proto.CompactTextString(m) } +func (*Session) ProtoMessage() {} +func (*Session) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{18} +} +func (m *Session) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_Session.Unmarshal(m, b) +} +func (m *Session) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_Session.Marshal(b, m, deterministic) +} +func (dst *Session) XXX_Merge(src proto.Message) { + xxx_messageInfo_Session.Merge(dst, src) +} +func (m *Session) XXX_Size() int { + return xxx_messageInfo_Session.Size(m) +} +func (m *Session) XXX_DiscardUnknown() { + xxx_messageInfo_Session.DiscardUnknown(m) +} + +var xxx_messageInfo_Session proto.InternalMessageInfo + +func (m *Session) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *Session) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *Session) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +func (m *Session) GetCircuit() *Circuit { + if m != nil { + return m.Circuit + } + return nil +} + +type ListSessionsRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListSessionsRequest) Reset() { *m = ListSessionsRequest{} } +func (m *ListSessionsRequest) String() string { return proto.CompactTextString(m) } +func (*ListSessionsRequest) ProtoMessage() {} +func (*ListSessionsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{19} +} +func (m *ListSessionsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListSessionsRequest.Unmarshal(m, b) +} +func (m *ListSessionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListSessionsRequest.Marshal(b, m, deterministic) +} +func (dst *ListSessionsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSessionsRequest.Merge(dst, src) +} +func (m *ListSessionsRequest) XXX_Size() int { + return xxx_messageInfo_ListSessionsRequest.Size(m) +} +func (m *ListSessionsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListSessionsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ListSessionsRequest proto.InternalMessageInfo + +type ListSessionsResponse struct { + Sessions []*Session `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ListSessionsResponse) Reset() { *m = ListSessionsResponse{} } +func (m *ListSessionsResponse) String() string { return proto.CompactTextString(m) } +func (*ListSessionsResponse) ProtoMessage() {} +func (*ListSessionsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{20} +} +func (m *ListSessionsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ListSessionsResponse.Unmarshal(m, b) +} +func (m *ListSessionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ListSessionsResponse.Marshal(b, m, deterministic) +} +func (dst *ListSessionsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSessionsResponse.Merge(dst, src) +} +func (m *ListSessionsResponse) XXX_Size() int { + return xxx_messageInfo_ListSessionsResponse.Size(m) +} +func (m *ListSessionsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListSessionsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ListSessionsResponse proto.InternalMessageInfo + +func (m *ListSessionsResponse) GetSessions() []*Session { + if m != nil { + return m.Sessions + } + return nil +} + +type RemoveSessionRequest struct { + SessionId string `protobuf:"bytes,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Now bool `protobuf:"varint,2,opt,name=now,proto3" json:"now,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *RemoveSessionRequest) Reset() { *m = RemoveSessionRequest{} } +func (m *RemoveSessionRequest) String() string { return proto.CompactTextString(m) } +func (*RemoveSessionRequest) ProtoMessage() {} +func (*RemoveSessionRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{21} +} +func (m *RemoveSessionRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_RemoveSessionRequest.Unmarshal(m, b) +} +func (m *RemoveSessionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_RemoveSessionRequest.Marshal(b, m, deterministic) +} +func (dst *RemoveSessionRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoveSessionRequest.Merge(dst, src) +} +func (m *RemoveSessionRequest) XXX_Size() int { + return xxx_messageInfo_RemoveSessionRequest.Size(m) +} +func (m *RemoveSessionRequest) XXX_DiscardUnknown() { + xxx_messageInfo_RemoveSessionRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_RemoveSessionRequest proto.InternalMessageInfo + +func (m *RemoveSessionRequest) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *RemoveSessionRequest) GetNow() bool { + if m != nil { + return m.Now + } + return false +} + +type StreamMetricsRequest struct { + Matchers []*StreamMetricsRequest_MetricMatcher `protobuf:"bytes,1,rep,name=matchers,proto3" json:"matchers,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMetricsRequest) Reset() { *m = StreamMetricsRequest{} } +func (m *StreamMetricsRequest) String() string { return proto.CompactTextString(m) } +func (*StreamMetricsRequest) ProtoMessage() {} +func (*StreamMetricsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{22} +} +func (m *StreamMetricsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMetricsRequest.Unmarshal(m, b) +} +func (m *StreamMetricsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMetricsRequest.Marshal(b, m, deterministic) +} +func (dst *StreamMetricsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMetricsRequest.Merge(dst, src) +} +func (m *StreamMetricsRequest) XXX_Size() int { + return xxx_messageInfo_StreamMetricsRequest.Size(m) +} +func (m *StreamMetricsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMetricsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMetricsRequest proto.InternalMessageInfo + +func (m *StreamMetricsRequest) GetMatchers() []*StreamMetricsRequest_MetricMatcher { + if m != nil { + return m.Matchers + } + return nil +} + +type StreamMetricsRequest_MetricMatcher struct { + NameRegex string `protobuf:"bytes,1,opt,name=nameRegex,proto3" json:"nameRegex,omitempty"` + SourceIDRegex string `protobuf:"bytes,2,opt,name=sourceIDRegex,proto3" json:"sourceIDRegex,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMetricsRequest_MetricMatcher) Reset() { *m = StreamMetricsRequest_MetricMatcher{} } +func (m *StreamMetricsRequest_MetricMatcher) String() string { return proto.CompactTextString(m) } +func (*StreamMetricsRequest_MetricMatcher) ProtoMessage() {} +func (*StreamMetricsRequest_MetricMatcher) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{22, 0} +} +func (m *StreamMetricsRequest_MetricMatcher) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMetricsRequest_MetricMatcher.Unmarshal(m, b) +} +func (m *StreamMetricsRequest_MetricMatcher) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMetricsRequest_MetricMatcher.Marshal(b, m, deterministic) +} +func (dst *StreamMetricsRequest_MetricMatcher) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMetricsRequest_MetricMatcher.Merge(dst, src) +} +func (m *StreamMetricsRequest_MetricMatcher) XXX_Size() int { + return xxx_messageInfo_StreamMetricsRequest_MetricMatcher.Size(m) +} +func (m *StreamMetricsRequest_MetricMatcher) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMetricsRequest_MetricMatcher.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMetricsRequest_MetricMatcher proto.InternalMessageInfo + +func (m *StreamMetricsRequest_MetricMatcher) GetNameRegex() string { + if m != nil { + return m.NameRegex + } + return "" +} + +func (m *StreamMetricsRequest_MetricMatcher) GetSourceIDRegex() string { + if m != nil { + return m.SourceIDRegex + } + return "" +} + +type StreamMetricsEvent struct { + SourceId string `protobuf:"bytes,1,opt,name=sourceId,proto3" json:"sourceId,omitempty"` + Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Tags map[string]string `protobuf:"bytes,3,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + IntMetrics map[string]int64 `protobuf:"bytes,4,rep,name=intMetrics,proto3" json:"intMetrics,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + FloatMetrics map[string]float64 `protobuf:"bytes,5,rep,name=floatMetrics,proto3" json:"floatMetrics,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"` + IntervalMetrics []*StreamMetricsEvent_IntervalMetric `protobuf:"bytes,6,rep,name=intervalMetrics,proto3" json:"intervalMetrics,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMetricsEvent) Reset() { *m = StreamMetricsEvent{} } +func (m *StreamMetricsEvent) String() string { return proto.CompactTextString(m) } +func (*StreamMetricsEvent) ProtoMessage() {} +func (*StreamMetricsEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{23} +} +func (m *StreamMetricsEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMetricsEvent.Unmarshal(m, b) +} +func (m *StreamMetricsEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMetricsEvent.Marshal(b, m, deterministic) +} +func (dst *StreamMetricsEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMetricsEvent.Merge(dst, src) +} +func (m *StreamMetricsEvent) XXX_Size() int { + return xxx_messageInfo_StreamMetricsEvent.Size(m) +} +func (m *StreamMetricsEvent) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMetricsEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMetricsEvent proto.InternalMessageInfo + +func (m *StreamMetricsEvent) GetSourceId() string { + if m != nil { + return m.SourceId + } + return "" +} + +func (m *StreamMetricsEvent) GetTimestamp() *timestamp.Timestamp { + if m != nil { + return m.Timestamp + } + return nil +} + +func (m *StreamMetricsEvent) GetTags() map[string]string { + if m != nil { + return m.Tags + } + return nil +} + +func (m *StreamMetricsEvent) GetIntMetrics() map[string]int64 { + if m != nil { + return m.IntMetrics + } + return nil +} + +func (m *StreamMetricsEvent) GetFloatMetrics() map[string]float64 { + if m != nil { + return m.FloatMetrics + } + return nil +} + +func (m *StreamMetricsEvent) GetIntervalMetrics() []*StreamMetricsEvent_IntervalMetric { + if m != nil { + return m.IntervalMetrics + } + return nil +} + +type StreamMetricsEvent_IntervalMetric struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + IntervalStartUTC *timestamp.Timestamp `protobuf:"bytes,2,opt,name=intervalStartUTC,proto3" json:"intervalStartUTC,omitempty"` + IntervalEndUTC *timestamp.Timestamp `protobuf:"bytes,3,opt,name=intervalEndUTC,proto3" json:"intervalEndUTC,omitempty"` + Values map[string]uint64 `protobuf:"bytes,4,rep,name=values,proto3" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamMetricsEvent_IntervalMetric) Reset() { *m = StreamMetricsEvent_IntervalMetric{} } +func (m *StreamMetricsEvent_IntervalMetric) String() string { return proto.CompactTextString(m) } +func (*StreamMetricsEvent_IntervalMetric) ProtoMessage() {} +func (*StreamMetricsEvent_IntervalMetric) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{23, 3} +} +func (m *StreamMetricsEvent_IntervalMetric) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamMetricsEvent_IntervalMetric.Unmarshal(m, b) +} +func (m *StreamMetricsEvent_IntervalMetric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamMetricsEvent_IntervalMetric.Marshal(b, m, deterministic) +} +func (dst *StreamMetricsEvent_IntervalMetric) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamMetricsEvent_IntervalMetric.Merge(dst, src) +} +func (m *StreamMetricsEvent_IntervalMetric) XXX_Size() int { + return xxx_messageInfo_StreamMetricsEvent_IntervalMetric.Size(m) +} +func (m *StreamMetricsEvent_IntervalMetric) XXX_DiscardUnknown() { + xxx_messageInfo_StreamMetricsEvent_IntervalMetric.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamMetricsEvent_IntervalMetric proto.InternalMessageInfo + +func (m *StreamMetricsEvent_IntervalMetric) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *StreamMetricsEvent_IntervalMetric) GetIntervalStartUTC() *timestamp.Timestamp { + if m != nil { + return m.IntervalStartUTC + } + return nil +} + +func (m *StreamMetricsEvent_IntervalMetric) GetIntervalEndUTC() *timestamp.Timestamp { + if m != nil { + return m.IntervalEndUTC + } + return nil +} + +func (m *StreamMetricsEvent_IntervalMetric) GetValues() map[string]uint64 { + if m != nil { + return m.Values + } + return nil +} + +type StreamSessionsRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamSessionsRequest) Reset() { *m = StreamSessionsRequest{} } +func (m *StreamSessionsRequest) String() string { return proto.CompactTextString(m) } +func (*StreamSessionsRequest) ProtoMessage() {} +func (*StreamSessionsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{24} +} +func (m *StreamSessionsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamSessionsRequest.Unmarshal(m, b) +} +func (m *StreamSessionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamSessionsRequest.Marshal(b, m, deterministic) +} +func (dst *StreamSessionsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamSessionsRequest.Merge(dst, src) +} +func (m *StreamSessionsRequest) XXX_Size() int { + return xxx_messageInfo_StreamSessionsRequest.Size(m) +} +func (m *StreamSessionsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_StreamSessionsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamSessionsRequest proto.InternalMessageInfo + +type StreamSessionsEvent struct { + EventType StreamSessionEventType `protobuf:"varint,1,opt,name=eventType,proto3,enum=mgmt_pb.StreamSessionEventType" json:"eventType,omitempty"` + SessionId string `protobuf:"bytes,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + ClientId string `protobuf:"bytes,3,opt,name=clientId,proto3" json:"clientId,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=serviceId,proto3" json:"serviceId,omitempty"` + Circuit *Circuit `protobuf:"bytes,5,opt,name=circuit,proto3" json:"circuit,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamSessionsEvent) Reset() { *m = StreamSessionsEvent{} } +func (m *StreamSessionsEvent) String() string { return proto.CompactTextString(m) } +func (*StreamSessionsEvent) ProtoMessage() {} +func (*StreamSessionsEvent) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{25} +} +func (m *StreamSessionsEvent) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamSessionsEvent.Unmarshal(m, b) +} +func (m *StreamSessionsEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamSessionsEvent.Marshal(b, m, deterministic) +} +func (dst *StreamSessionsEvent) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamSessionsEvent.Merge(dst, src) +} +func (m *StreamSessionsEvent) XXX_Size() int { + return xxx_messageInfo_StreamSessionsEvent.Size(m) +} +func (m *StreamSessionsEvent) XXX_DiscardUnknown() { + xxx_messageInfo_StreamSessionsEvent.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamSessionsEvent proto.InternalMessageInfo + +func (m *StreamSessionsEvent) GetEventType() StreamSessionEventType { + if m != nil { + return m.EventType + } + return StreamSessionEventType_SessionCreated +} + +func (m *StreamSessionsEvent) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *StreamSessionsEvent) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *StreamSessionsEvent) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +func (m *StreamSessionsEvent) GetCircuit() *Circuit { + if m != nil { + return m.Circuit + } + return nil +} + +type ToggleSessionTracesRequest struct { + Enable bool `protobuf:"varint,1,opt,name=enable,proto3" json:"enable,omitempty"` + ServiceRegex string `protobuf:"bytes,2,opt,name=serviceRegex,proto3" json:"serviceRegex,omitempty"` + ClientRegex string `protobuf:"bytes,3,opt,name=clientRegex,proto3" json:"clientRegex,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ToggleSessionTracesRequest) Reset() { *m = ToggleSessionTracesRequest{} } +func (m *ToggleSessionTracesRequest) String() string { return proto.CompactTextString(m) } +func (*ToggleSessionTracesRequest) ProtoMessage() {} +func (*ToggleSessionTracesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{26} +} +func (m *ToggleSessionTracesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ToggleSessionTracesRequest.Unmarshal(m, b) +} +func (m *ToggleSessionTracesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ToggleSessionTracesRequest.Marshal(b, m, deterministic) +} +func (dst *ToggleSessionTracesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ToggleSessionTracesRequest.Merge(dst, src) +} +func (m *ToggleSessionTracesRequest) XXX_Size() int { + return xxx_messageInfo_ToggleSessionTracesRequest.Size(m) +} +func (m *ToggleSessionTracesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ToggleSessionTracesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ToggleSessionTracesRequest proto.InternalMessageInfo + +func (m *ToggleSessionTracesRequest) GetEnable() bool { + if m != nil { + return m.Enable + } + return false +} + +func (m *ToggleSessionTracesRequest) GetServiceRegex() string { + if m != nil { + return m.ServiceRegex + } + return "" +} + +func (m *ToggleSessionTracesRequest) GetClientRegex() string { + if m != nil { + return m.ClientRegex + } + return "" +} + +type StreamTracesRequest struct { + EnabledFilter bool `protobuf:"varint,1,opt,name=enabledFilter,proto3" json:"enabledFilter,omitempty"` + FilterType TraceFilterType `protobuf:"varint,2,opt,name=filterType,proto3,enum=mgmt_pb.TraceFilterType" json:"filterType,omitempty"` + ContentTypes []int32 `protobuf:"varint,3,rep,packed,name=contentTypes,proto3" json:"contentTypes,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *StreamTracesRequest) Reset() { *m = StreamTracesRequest{} } +func (m *StreamTracesRequest) String() string { return proto.CompactTextString(m) } +func (*StreamTracesRequest) ProtoMessage() {} +func (*StreamTracesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{27} +} +func (m *StreamTracesRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_StreamTracesRequest.Unmarshal(m, b) +} +func (m *StreamTracesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_StreamTracesRequest.Marshal(b, m, deterministic) +} +func (dst *StreamTracesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_StreamTracesRequest.Merge(dst, src) +} +func (m *StreamTracesRequest) XXX_Size() int { + return xxx_messageInfo_StreamTracesRequest.Size(m) +} +func (m *StreamTracesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_StreamTracesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_StreamTracesRequest proto.InternalMessageInfo + +func (m *StreamTracesRequest) GetEnabledFilter() bool { + if m != nil { + return m.EnabledFilter + } + return false +} + +func (m *StreamTracesRequest) GetFilterType() TraceFilterType { + if m != nil { + return m.FilterType + } + return TraceFilterType_EXCLUDE +} + +func (m *StreamTracesRequest) GetContentTypes() []int32 { + if m != nil { + return m.ContentTypes + } + return nil +} + +type InspectRequest struct { + AppRegex string `protobuf:"bytes,1,opt,name=appRegex,proto3" json:"appRegex,omitempty"` + RequestedValues []string `protobuf:"bytes,2,rep,name=requestedValues,proto3" json:"requestedValues,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectRequest) Reset() { *m = InspectRequest{} } +func (m *InspectRequest) String() string { return proto.CompactTextString(m) } +func (*InspectRequest) ProtoMessage() {} +func (*InspectRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{28} +} +func (m *InspectRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectRequest.Unmarshal(m, b) +} +func (m *InspectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectRequest.Marshal(b, m, deterministic) +} +func (dst *InspectRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectRequest.Merge(dst, src) +} +func (m *InspectRequest) XXX_Size() int { + return xxx_messageInfo_InspectRequest.Size(m) +} +func (m *InspectRequest) XXX_DiscardUnknown() { + xxx_messageInfo_InspectRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectRequest proto.InternalMessageInfo + +func (m *InspectRequest) GetAppRegex() string { + if m != nil { + return m.AppRegex + } + return "" +} + +func (m *InspectRequest) GetRequestedValues() []string { + if m != nil { + return m.RequestedValues + } + return nil +} + +type InspectResponse struct { + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + Errors []string `protobuf:"bytes,2,rep,name=errors,proto3" json:"errors,omitempty"` + Values []*InspectResponse_InspectValue `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectResponse) Reset() { *m = InspectResponse{} } +func (m *InspectResponse) String() string { return proto.CompactTextString(m) } +func (*InspectResponse) ProtoMessage() {} +func (*InspectResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{29} +} +func (m *InspectResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectResponse.Unmarshal(m, b) +} +func (m *InspectResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectResponse.Marshal(b, m, deterministic) +} +func (dst *InspectResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectResponse.Merge(dst, src) +} +func (m *InspectResponse) XXX_Size() int { + return xxx_messageInfo_InspectResponse.Size(m) +} +func (m *InspectResponse) XXX_DiscardUnknown() { + xxx_messageInfo_InspectResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectResponse proto.InternalMessageInfo + +func (m *InspectResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *InspectResponse) GetErrors() []string { + if m != nil { + return m.Errors + } + return nil +} + +func (m *InspectResponse) GetValues() []*InspectResponse_InspectValue { + if m != nil { + return m.Values + } + return nil +} + +type InspectResponse_InspectValue struct { + AppId string `protobuf:"bytes,1,opt,name=appId,proto3" json:"appId,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *InspectResponse_InspectValue) Reset() { *m = InspectResponse_InspectValue{} } +func (m *InspectResponse_InspectValue) String() string { return proto.CompactTextString(m) } +func (*InspectResponse_InspectValue) ProtoMessage() {} +func (*InspectResponse_InspectValue) Descriptor() ([]byte, []int) { + return fileDescriptor_mgmt_48769249f84eeebf, []int{29, 0} +} +func (m *InspectResponse_InspectValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_InspectResponse_InspectValue.Unmarshal(m, b) +} +func (m *InspectResponse_InspectValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_InspectResponse_InspectValue.Marshal(b, m, deterministic) +} +func (dst *InspectResponse_InspectValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_InspectResponse_InspectValue.Merge(dst, src) +} +func (m *InspectResponse_InspectValue) XXX_Size() int { + return xxx_messageInfo_InspectResponse_InspectValue.Size(m) +} +func (m *InspectResponse_InspectValue) XXX_DiscardUnknown() { + xxx_messageInfo_InspectResponse_InspectValue.DiscardUnknown(m) +} + +var xxx_messageInfo_InspectResponse_InspectValue proto.InternalMessageInfo + +func (m *InspectResponse_InspectValue) GetAppId() string { + if m != nil { + return m.AppId + } + return "" +} + +func (m *InspectResponse_InspectValue) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *InspectResponse_InspectValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +func init() { + proto.RegisterType((*Service)(nil), "mgmt_pb.Service") + proto.RegisterType((*ListServicesRequest)(nil), "mgmt_pb.ListServicesRequest") + proto.RegisterType((*ListServicesResponse)(nil), "mgmt_pb.ListServicesResponse") + proto.RegisterType((*CreateServiceRequest)(nil), "mgmt_pb.CreateServiceRequest") + proto.RegisterType((*RemoveServiceRequest)(nil), "mgmt_pb.RemoveServiceRequest") + proto.RegisterType((*GetServiceRequest)(nil), "mgmt_pb.GetServiceRequest") + proto.RegisterType((*GetServiceResponse)(nil), "mgmt_pb.GetServiceResponse") + proto.RegisterType((*Router)(nil), "mgmt_pb.Router") + proto.RegisterType((*ListRoutersRequest)(nil), "mgmt_pb.ListRoutersRequest") + proto.RegisterType((*ListRoutersResponse)(nil), "mgmt_pb.ListRoutersResponse") + proto.RegisterType((*CreateRouterRequest)(nil), "mgmt_pb.CreateRouterRequest") + proto.RegisterType((*RemoveRouterRequest)(nil), "mgmt_pb.RemoveRouterRequest") + proto.RegisterType((*Link)(nil), "mgmt_pb.Link") + proto.RegisterType((*ListLinksRequest)(nil), "mgmt_pb.ListLinksRequest") + proto.RegisterType((*ListLinksResponse)(nil), "mgmt_pb.ListLinksResponse") + proto.RegisterType((*SetLinkCostRequest)(nil), "mgmt_pb.SetLinkCostRequest") + proto.RegisterType((*SetLinkDownRequest)(nil), "mgmt_pb.SetLinkDownRequest") + proto.RegisterType((*Circuit)(nil), "mgmt_pb.Circuit") + proto.RegisterType((*Session)(nil), "mgmt_pb.Session") + proto.RegisterType((*ListSessionsRequest)(nil), "mgmt_pb.ListSessionsRequest") + proto.RegisterType((*ListSessionsResponse)(nil), "mgmt_pb.ListSessionsResponse") + proto.RegisterType((*RemoveSessionRequest)(nil), "mgmt_pb.RemoveSessionRequest") + proto.RegisterType((*StreamMetricsRequest)(nil), "mgmt_pb.StreamMetricsRequest") + proto.RegisterType((*StreamMetricsRequest_MetricMatcher)(nil), "mgmt_pb.StreamMetricsRequest.MetricMatcher") + proto.RegisterType((*StreamMetricsEvent)(nil), "mgmt_pb.StreamMetricsEvent") + proto.RegisterMapType((map[string]float64)(nil), "mgmt_pb.StreamMetricsEvent.FloatMetricsEntry") + proto.RegisterMapType((map[string]int64)(nil), "mgmt_pb.StreamMetricsEvent.IntMetricsEntry") + proto.RegisterMapType((map[string]string)(nil), "mgmt_pb.StreamMetricsEvent.TagsEntry") + proto.RegisterType((*StreamMetricsEvent_IntervalMetric)(nil), "mgmt_pb.StreamMetricsEvent.IntervalMetric") + proto.RegisterMapType((map[string]uint64)(nil), "mgmt_pb.StreamMetricsEvent.IntervalMetric.ValuesEntry") + proto.RegisterType((*StreamSessionsRequest)(nil), "mgmt_pb.StreamSessionsRequest") + proto.RegisterType((*StreamSessionsEvent)(nil), "mgmt_pb.StreamSessionsEvent") + proto.RegisterType((*ToggleSessionTracesRequest)(nil), "mgmt_pb.ToggleSessionTracesRequest") + proto.RegisterType((*StreamTracesRequest)(nil), "mgmt_pb.StreamTracesRequest") + proto.RegisterType((*InspectRequest)(nil), "mgmt_pb.InspectRequest") + proto.RegisterType((*InspectResponse)(nil), "mgmt_pb.InspectResponse") + proto.RegisterType((*InspectResponse_InspectValue)(nil), "mgmt_pb.InspectResponse.InspectValue") + proto.RegisterEnum("mgmt_pb.ContentType", ContentType_name, ContentType_value) + proto.RegisterEnum("mgmt_pb.StreamSessionEventType", StreamSessionEventType_name, StreamSessionEventType_value) + proto.RegisterEnum("mgmt_pb.TraceFilterType", TraceFilterType_name, TraceFilterType_value) +} + +func init() { proto.RegisterFile("mgmt.proto", fileDescriptor_mgmt_48769249f84eeebf) } + +var fileDescriptor_mgmt_48769249f84eeebf = []byte{ + // 1552 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x57, 0x5b, 0x6f, 0xdc, 0x44, + 0x14, 0xae, 0x77, 0x37, 0xbb, 0x9b, 0x93, 0x26, 0xd9, 0x4e, 0xd2, 0x76, 0xbb, 0x2d, 0x6d, 0xe4, + 0x16, 0x11, 0x52, 0xd8, 0xaa, 0x2d, 0x82, 0x14, 0xa9, 0x50, 0x9a, 0x4b, 0x15, 0x91, 0x5a, 0xc5, + 0xd9, 0x56, 0x88, 0x17, 0xe4, 0xd8, 0x93, 0xad, 0xd5, 0x5d, 0xdb, 0xd8, 0xb3, 0x29, 0xe1, 0x05, + 0x89, 0x7f, 0x40, 0x11, 0x20, 0x6e, 0x6f, 0x5c, 0xde, 0x80, 0x07, 0x1e, 0x0a, 0xa5, 0x5c, 0xfe, + 0x02, 0x4f, 0xfc, 0x1c, 0x34, 0x67, 0xc6, 0xe3, 0xb1, 0xbd, 0x24, 0xed, 0xdb, 0xcc, 0xf7, 0x9d, + 0x73, 0x7c, 0xe6, 0x1c, 0xcf, 0xe7, 0x63, 0x80, 0x61, 0x7f, 0xc8, 0xba, 0x51, 0x1c, 0xb2, 0x90, + 0x34, 0xf8, 0xfa, 0xdd, 0x68, 0xbb, 0x73, 0xa6, 0x1f, 0x86, 0xfd, 0x01, 0xbd, 0x80, 0xf0, 0xf6, + 0x68, 0xe7, 0x02, 0xf3, 0x87, 0x34, 0x61, 0xce, 0x30, 0x12, 0x96, 0xe6, 0x08, 0x1a, 0x5b, 0x34, + 0xde, 0xf5, 0x5d, 0x4a, 0x66, 0xa0, 0xe2, 0x7b, 0x6d, 0x63, 0xc1, 0x58, 0x9c, 0xb4, 0x2b, 0xbe, + 0x47, 0xda, 0xd0, 0xd8, 0xf6, 0x03, 0xcf, 0x0f, 0xfa, 0xed, 0x0a, 0x82, 0xe9, 0x96, 0x2c, 0xc2, + 0x2c, 0x0d, 0xbc, 0x28, 0xf4, 0x03, 0xf6, 0x86, 0xe7, 0xc5, 0x34, 0x49, 0xda, 0x55, 0xb4, 0x28, + 0xc2, 0xe4, 0x18, 0xd4, 0x69, 0x1f, 0x0d, 0x6a, 0x68, 0x20, 0x77, 0xe6, 0x51, 0x98, 0xdb, 0xf4, + 0x13, 0x26, 0x1f, 0x9d, 0xd8, 0xf4, 0xbd, 0x11, 0x4d, 0x98, 0xb9, 0x0a, 0xf3, 0x79, 0x38, 0x89, + 0xc2, 0x20, 0xa1, 0xe4, 0x05, 0x68, 0x26, 0x12, 0x6b, 0x1b, 0x0b, 0xd5, 0xc5, 0xa9, 0x4b, 0xad, + 0xae, 0x3c, 0x62, 0x57, 0x1a, 0xdb, 0xca, 0xc2, 0xbc, 0x0e, 0xf3, 0x2b, 0x31, 0x75, 0x18, 0x4d, + 0x29, 0x11, 0x9d, 0x2c, 0x41, 0x43, 0xda, 0xe0, 0x29, 0xc7, 0x05, 0x49, 0x0d, 0xcc, 0x97, 0x60, + 0xde, 0xa6, 0xc3, 0x70, 0xb7, 0x18, 0xe3, 0x14, 0x4c, 0x4a, 0x93, 0x8d, 0xb4, 0x56, 0x19, 0x60, + 0x5e, 0x84, 0x23, 0x37, 0x28, 0x7b, 0x2a, 0x97, 0x6b, 0x40, 0x74, 0x17, 0x79, 0xe0, 0xa7, 0x49, + 0xf5, 0x23, 0x03, 0xea, 0x76, 0x38, 0x62, 0x34, 0x2e, 0xb5, 0x70, 0x01, 0xa6, 0x76, 0xfc, 0xa0, + 0x4f, 0xe3, 0x28, 0xf6, 0x03, 0x26, 0xdb, 0xa8, 0x43, 0xbc, 0x95, 0x03, 0x3f, 0x61, 0x34, 0xa0, + 0x71, 0xa1, 0x95, 0x05, 0x98, 0x1f, 0xc3, 0x0d, 0x83, 0x80, 0xba, 0x8c, 0x7a, 0xd8, 0xcd, 0xa6, + 0x9d, 0x01, 0xe6, 0x3c, 0x10, 0xde, 0x39, 0x91, 0x87, 0xea, 0xe7, 0x35, 0xd1, 0x66, 0x85, 0xca, + 0xd3, 0x3d, 0x0f, 0x8d, 0x58, 0x40, 0xb2, 0x9b, 0xb3, 0xea, 0x74, 0xc2, 0xd4, 0x4e, 0x79, 0xf3, + 0x35, 0x98, 0x13, 0xbd, 0x94, 0x84, 0xac, 0xe9, 0x73, 0x50, 0x17, 0x16, 0xb2, 0x3c, 0xa5, 0x00, + 0x92, 0x36, 0x2f, 0xc2, 0x9c, 0xe8, 0x63, 0xde, 0xbf, 0x03, 0x4d, 0x61, 0xa0, 0x5a, 0xa2, 0xf6, + 0xe6, 0x43, 0x03, 0x6a, 0x9b, 0x7e, 0x70, 0xaf, 0x54, 0xcd, 0x16, 0x54, 0x93, 0xd8, 0x95, 0x55, + 0xe4, 0x4b, 0x8e, 0x78, 0x09, 0x93, 0x15, 0xe3, 0x4b, 0x32, 0x0f, 0x13, 0x09, 0x73, 0x18, 0x95, + 0xef, 0xbb, 0xd8, 0x10, 0x02, 0x35, 0x2f, 0xbc, 0x1f, 0xb4, 0x27, 0xb0, 0x6c, 0xb8, 0xe6, 0x98, + 0x1b, 0x26, 0xac, 0x5d, 0x5f, 0x30, 0x16, 0x27, 0x6c, 0x5c, 0x93, 0xd3, 0x00, 0x49, 0xec, 0x6e, + 0x3a, 0x8c, 0x06, 0xee, 0x5e, 0xbb, 0xb1, 0x60, 0x2c, 0x56, 0x6d, 0x0d, 0xe1, 0xbc, 0x97, 0xb0, + 0x94, 0x6f, 0x0a, 0x3e, 0x43, 0x4c, 0x02, 0x2d, 0x5e, 0x6f, 0x9e, 0xbd, 0xea, 0xc1, 0x32, 0x1c, + 0xd1, 0x30, 0xd9, 0x81, 0xb3, 0x30, 0x31, 0xe0, 0x80, 0xac, 0xff, 0xb4, 0x2a, 0x1f, 0x37, 0xb3, + 0x05, 0xc7, 0x5f, 0xcd, 0x2d, 0x8a, 0x8e, 0x2b, 0x61, 0xc2, 0xd2, 0xd2, 0x1d, 0x83, 0x3a, 0xa7, + 0x55, 0xe1, 0xe4, 0x4e, 0x9d, 0xa7, 0x92, 0x9d, 0x47, 0x8b, 0xb0, 0x1a, 0xde, 0x0f, 0x9e, 0x20, + 0x02, 0x56, 0xa9, 0x92, 0x55, 0xc9, 0xbc, 0x0c, 0x8d, 0x15, 0x3f, 0x76, 0x47, 0x3e, 0xe3, 0x74, + 0xe4, 0xb0, 0xbb, 0x98, 0xf2, 0xa4, 0x8d, 0x6b, 0x5e, 0x6e, 0x71, 0x8e, 0x0a, 0x82, 0x32, 0xf1, + 0x0f, 0xb9, 0xa8, 0x25, 0x89, 0x1f, 0x06, 0xa5, 0x1e, 0x76, 0xa0, 0xe9, 0x0e, 0x7c, 0x1a, 0xb0, + 0x0d, 0x4f, 0x36, 0x52, 0xed, 0xf3, 0x17, 0xb5, 0x5a, 0xb8, 0xa8, 0xfc, 0x4a, 0xba, 0x22, 0x13, + 0xec, 0xad, 0x7e, 0x25, 0x65, 0x86, 0x76, 0x6a, 0x90, 0xc9, 0x1b, 0x26, 0x51, 0x96, 0xb7, 0x14, + 0xd6, 0xe5, 0x4d, 0x60, 0x63, 0xe4, 0x0d, 0x09, 0x5b, 0x59, 0x98, 0xeb, 0x99, 0x34, 0x09, 0x4a, + 0xd7, 0x19, 0x44, 0x74, 0x9d, 0x91, 0x00, 0x7f, 0x55, 0x83, 0xf0, 0xbe, 0xac, 0x2d, 0x5f, 0x9a, + 0xbf, 0x18, 0x30, 0xbf, 0xc5, 0x62, 0xea, 0x0c, 0x6f, 0x52, 0x16, 0xfb, 0x6e, 0x9a, 0x26, 0xb9, + 0x01, 0xcd, 0xa1, 0xc3, 0xdc, 0xbb, 0xd9, 0xfd, 0x3c, 0x9f, 0xa5, 0x33, 0xc6, 0xa1, 0x2b, 0xb6, + 0x37, 0x85, 0x8f, 0xad, 0x9c, 0x3b, 0x5b, 0x30, 0x9d, 0xa3, 0x78, 0x8a, 0x81, 0x33, 0xa4, 0x36, + 0xed, 0xd3, 0xf7, 0xd3, 0x14, 0x15, 0x40, 0xce, 0xc1, 0x74, 0x12, 0x8e, 0x62, 0x97, 0x6e, 0xac, + 0x0a, 0x0b, 0xd1, 0xa0, 0x3c, 0x68, 0x3e, 0x68, 0x00, 0xc9, 0x65, 0xb1, 0xb6, 0x4b, 0x03, 0xbc, + 0xd1, 0xd2, 0x4e, 0xdd, 0xe8, 0x74, 0x4f, 0x96, 0x61, 0x52, 0x7d, 0xf7, 0x30, 0xe8, 0xd4, 0xa5, + 0x4e, 0x57, 0x7c, 0x19, 0xbb, 0xe9, 0x97, 0xb1, 0xdb, 0x4b, 0x2d, 0xec, 0xcc, 0x98, 0x5c, 0x81, + 0x1a, 0x73, 0xfa, 0x5c, 0x13, 0x79, 0x19, 0x9e, 0x1d, 0x5f, 0x06, 0x4c, 0xa0, 0xdb, 0x73, 0xfa, + 0xc9, 0x5a, 0xc0, 0xe2, 0x3d, 0x1b, 0x5d, 0xc8, 0x9b, 0x00, 0x7e, 0xc0, 0xa4, 0x49, 0xbb, 0xb6, + 0x5f, 0x1d, 0x45, 0x80, 0x0d, 0x65, 0x2d, 0xc2, 0x68, 0xee, 0xe4, 0x2d, 0x38, 0xbc, 0x33, 0x08, + 0x1d, 0x15, 0x6e, 0x02, 0xc3, 0xbd, 0xb8, 0x5f, 0xb8, 0x75, 0xcd, 0x5e, 0x04, 0xcc, 0x85, 0x20, + 0x3d, 0x98, 0xf5, 0x03, 0x46, 0xe3, 0x5d, 0x67, 0x90, 0x46, 0xad, 0x63, 0xd4, 0xa5, 0x03, 0x92, + 0xd4, 0x5c, 0xec, 0x62, 0x88, 0xce, 0x2b, 0x30, 0xa9, 0x0a, 0xc1, 0xdf, 0xb9, 0x7b, 0x74, 0x4f, + 0xb6, 0x83, 0x2f, 0xf9, 0x7d, 0xdd, 0x75, 0x06, 0x23, 0x2a, 0x5b, 0x2b, 0x36, 0xaf, 0x56, 0x96, + 0x8d, 0xce, 0x55, 0x98, 0x2d, 0x14, 0xe0, 0x20, 0xf7, 0xaa, 0xee, 0xfe, 0x3a, 0x1c, 0x29, 0x1d, + 0xf8, 0xa0, 0x00, 0x86, 0x1e, 0xe0, 0x51, 0x05, 0x66, 0xf2, 0x87, 0xe3, 0x82, 0xc3, 0x5f, 0x4e, + 0xe9, 0x8f, 0x6b, 0xb2, 0x0e, 0xad, 0xf4, 0xc8, 0x5b, 0xcc, 0x89, 0xd9, 0xed, 0xde, 0xca, 0x13, + 0xbc, 0x51, 0x25, 0x1f, 0x72, 0x1d, 0x66, 0x52, 0x6c, 0x2d, 0xf0, 0x78, 0x94, 0xea, 0x81, 0x51, + 0x0a, 0x1e, 0xc4, 0x82, 0x3a, 0xe6, 0x9f, 0xbe, 0x5d, 0x2f, 0x3f, 0x79, 0xe3, 0xba, 0x77, 0xd0, + 0x51, 0xbc, 0x17, 0x32, 0x4a, 0xe7, 0x0a, 0x4c, 0x69, 0xf0, 0x41, 0xd5, 0xab, 0x69, 0xd5, 0x33, + 0x8f, 0xc3, 0x51, 0xf1, 0xcc, 0xa2, 0xe4, 0xfd, 0x6b, 0xc0, 0x5c, 0x9e, 0x11, 0xd7, 0xf5, 0x2a, + 0x4c, 0x52, 0xbe, 0xe8, 0xed, 0x45, 0xa2, 0xc0, 0x33, 0x97, 0xce, 0x14, 0xd2, 0x97, 0x0e, 0x6b, + 0xa9, 0x99, 0x9d, 0x79, 0xe4, 0xb5, 0xae, 0x52, 0xd4, 0x3a, 0x5d, 0xe4, 0xab, 0xfb, 0x89, 0x7c, + 0x6d, 0x1f, 0x91, 0x9f, 0x38, 0x48, 0xe4, 0x3f, 0x80, 0x4e, 0x2f, 0xec, 0xf7, 0x07, 0xa9, 0x0e, + 0xf7, 0x62, 0x27, 0x1b, 0x65, 0x71, 0xf2, 0x0d, 0x9c, 0xed, 0x81, 0x38, 0x5d, 0xd3, 0x96, 0x3b, + 0x62, 0xc2, 0xe1, 0x24, 0x1d, 0xf6, 0x32, 0x8d, 0xcb, 0x61, 0x7c, 0x6c, 0x13, 0xf9, 0x0a, 0x13, + 0x71, 0x04, 0x1d, 0x32, 0xbf, 0x50, 0x65, 0xcd, 0x3f, 0xf5, 0x1c, 0x4c, 0x8b, 0xe7, 0x78, 0xeb, + 0xfe, 0x20, 0x1d, 0x8f, 0x9a, 0x76, 0x1e, 0x24, 0xcb, 0x00, 0x3b, 0xb8, 0xc2, 0xea, 0x57, 0xb0, + 0xfa, 0x6d, 0x75, 0x50, 0x8c, 0xb8, 0xae, 0x78, 0x5b, 0xb3, 0xe5, 0xd9, 0xbb, 0x61, 0xc0, 0x64, + 0x1b, 0x84, 0x2e, 0x4e, 0xd8, 0x39, 0xcc, 0xbc, 0xc3, 0x2f, 0x52, 0x12, 0x51, 0x97, 0x69, 0xd3, + 0x96, 0x13, 0x45, 0xba, 0xea, 0xab, 0x3d, 0x1f, 0x40, 0x63, 0x61, 0x46, 0x3d, 0xf1, 0xf6, 0xc9, + 0x6f, 0x79, 0x11, 0x36, 0xff, 0x31, 0xb8, 0x44, 0xc8, 0xc0, 0xf2, 0xcb, 0xd9, 0x86, 0x46, 0x32, + 0x72, 0x5d, 0x3e, 0xb6, 0x8a, 0x93, 0xa6, 0x5b, 0xac, 0x7f, 0x1c, 0x87, 0x71, 0x1a, 0x4e, 0xee, + 0xc8, 0x55, 0x75, 0x69, 0x8a, 0x9a, 0x5e, 0x88, 0x9d, 0xee, 0xf1, 0xe9, 0xea, 0x8e, 0x58, 0x70, + 0x58, 0xc7, 0xf9, 0x95, 0x70, 0xa2, 0x48, 0x7d, 0x73, 0xc4, 0x46, 0x29, 0x47, 0x45, 0x53, 0x0e, + 0x75, 0x79, 0xaa, 0x9a, 0xf4, 0x2d, 0x3d, 0xae, 0xc3, 0xd4, 0x4a, 0x56, 0x3d, 0xd2, 0x84, 0xda, + 0x3b, 0x34, 0x0e, 0x5b, 0x87, 0xc8, 0x29, 0x38, 0x3e, 0xe6, 0x17, 0x89, 0x1b, 0xb5, 0x3e, 0xb6, + 0xc8, 0x33, 0xd0, 0x1e, 0xf7, 0xa7, 0x84, 0xf4, 0x03, 0xa4, 0xc7, 0xfd, 0x02, 0x21, 0xfd, 0x09, + 0xd2, 0xe3, 0xfe, 0x6e, 0x90, 0xfe, 0xd4, 0x22, 0x1d, 0x38, 0x5a, 0xfa, 0x8d, 0x41, 0xee, 0x33, + 0x8b, 0x9c, 0x84, 0x63, 0xe5, 0xff, 0x15, 0x24, 0x3f, 0x47, 0xb2, 0xfc, 0x17, 0x80, 0xe4, 0x97, + 0x56, 0x7a, 0xa0, 0xc2, 0xcf, 0x00, 0xb2, 0x5f, 0x21, 0x3b, 0x66, 0xd0, 0x47, 0xf6, 0x6b, 0x64, + 0xc7, 0x8c, 0xf1, 0xc8, 0x7e, 0x63, 0x91, 0x13, 0x62, 0xae, 0xd2, 0xc7, 0x5e, 0xa4, 0xbe, 0xc5, + 0xa3, 0x94, 0xa6, 0x5f, 0xe4, 0xbe, 0xc3, 0x6c, 0xcb, 0xf3, 0x2d, 0x92, 0xdf, 0xeb, 0xa4, 0x36, + 0xba, 0x22, 0xf9, 0x83, 0x95, 0xf5, 0x26, 0x27, 0x76, 0xc8, 0xfe, 0xa8, 0xf5, 0x26, 0x3f, 0xe6, + 0x21, 0xfd, 0x53, 0xae, 0xf8, 0xfa, 0xfc, 0x86, 0xf4, 0xcf, 0x48, 0x8f, 0x1b, 0xb2, 0x90, 0x7e, + 0x28, 0xf2, 0x2a, 0xa9, 0x3b, 0x92, 0xbf, 0x5a, 0xe4, 0x34, 0x9c, 0x18, 0x2b, 0xc3, 0xc8, 0xff, + 0x86, 0x79, 0x8f, 0x11, 0x63, 0x64, 0x1f, 0x59, 0x64, 0x01, 0x4e, 0x0a, 0x41, 0xbb, 0xe5, 0x47, + 0x34, 0xa7, 0x2b, 0x68, 0xf1, 0xbb, 0x45, 0xce, 0xc2, 0xe9, 0xff, 0x97, 0x3c, 0x34, 0x7a, 0xac, + 0x3d, 0xa4, 0xcc, 0xfe, 0x81, 0x0d, 0xd1, 0xd9, 0x2c, 0x81, 0x3f, 0x2d, 0x72, 0x1c, 0x48, 0x5e, + 0x39, 0x90, 0xf8, 0xcb, 0x22, 0x6d, 0x98, 0x2b, 0xdc, 0x4e, 0x64, 0xfe, 0xb6, 0x96, 0xee, 0xa6, + 0xe5, 0x28, 0x7e, 0x2d, 0x08, 0x81, 0x19, 0x89, 0x89, 0xf7, 0xca, 0x6b, 0x1d, 0xd2, 0xb0, 0x55, + 0x3a, 0xa0, 0x1c, 0x33, 0x34, 0xec, 0x56, 0x4c, 0x13, 0x1a, 0xb0, 0x56, 0x85, 0x63, 0x52, 0xee, + 0x6f, 0x47, 0x1e, 0xfa, 0x56, 0x97, 0xce, 0xc3, 0x6c, 0x41, 0x19, 0xc9, 0x14, 0x34, 0xd6, 0xde, + 0x5e, 0xd9, 0xbc, 0xbd, 0xba, 0xd6, 0x3a, 0xc4, 0x37, 0x1b, 0x96, 0xd8, 0x18, 0xdb, 0x75, 0xfc, + 0x7c, 0x5f, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xbf, 0x2f, 0xe3, 0xf6, 0x95, 0x11, 0x00, 0x00, +} diff --git a/fabric/pb/mgmt_pb/mgmt.proto b/fabric/pb/mgmt_pb/mgmt.proto new file mode 100644 index 000000000..2306b17ea --- /dev/null +++ b/fabric/pb/mgmt_pb/mgmt.proto @@ -0,0 +1,244 @@ +syntax = "proto3"; + +package mgmt_pb; + +import "google/protobuf/timestamp.proto"; + +enum ContentType { + // Protoc says this has to be here + Zero = 0; + + // Services + ListServicesRequestType = 10001; + ListServicesResponseType = 10002; + CreateServiceRequestType = 10003; + RemoveServiceRequestType = 10005; + GetServiceRequestType = 10006; + GetServiceResponseType = 10007; + + // Routers + ListRoutersRequestType = 10010; + ListRoutersResponseType = 10011; + CreateRouterRequestType = 10012; + RemoveRouterRequestType = 10013; + + // Links + ListLinksRequestType = 10020; + ListLinksResponseType = 10021; + SetLinkCostRequestType = 10022; + SetLinkDownRequestType = 10023; + + // Sessions + ListSessionsRequestType = 10030; + ListSessionsResponseType = 10031; + RemoveSessionRequestType = 10032; + + // Streams + StreamMetricsRequestType = 10040; + StreamMetricsEventType = 10041; + StreamSessionsRequestType = 10042; + StreamSessionsEventType = 10043; + + TogglePipeTracesRequestType = 10044; + ToggleSessionTracesRequestType = 10045; + StreamTracesRequestType = 10046; + StreamTracesEventType = 10047; + + // Inspect + InspectRequestType = 10048; + InspectResponseType = 10049; +} + +// +// --- Service ------------------------------------------------------------------------------------------------------ // +// + +message Service { + string id = 1; + string binding = 2; + string endpointAddress = 3; + string egress = 4; +} + +message ListServicesRequest {} +message ListServicesResponse { + repeated Service services = 1; +} + +message CreateServiceRequest { + Service service = 1; +} + +message RemoveServiceRequest { + string serviceId = 1; +} + +message GetServiceRequest { + string serviceId = 1; +} +message GetServiceResponse { + Service service = 1; +} + + +// +// --- Router ------------------------------------------------------------------------------------------------------- // +// + +message Router { + string id = 1; + string fingerprint = 2; + string listenerAddress = 3; + bool connected = 4; +} + +message ListRoutersRequest {} +message ListRoutersResponse { + repeated Router routers = 1; +} + +message CreateRouterRequest { + Router router = 1; +} + +message RemoveRouterRequest { + string routerId = 1; +} + +// +// --- Link --------------------------------------------------------------------------------------------------------- // +// + +message Link { + string id = 1; + string src = 2; + string dst = 3; + string state = 4; + bool down = 5; + int32 cost = 6; + int64 srcLatency = 7; + int64 dstLatency = 8; +} + +message ListLinksRequest{} +message ListLinksResponse { + repeated Link links = 1; +} + +message SetLinkCostRequest { + string linkId = 1; + int32 cost = 2; +} + +message SetLinkDownRequest { + string linkId = 1; + bool down = 2; +} + +// +// --- Session ------------------------------------------------------------------------------------------------------ // +// + +message Circuit { + repeated string path = 1; + repeated string links = 2; +} + +message Session { + string id = 1; + string clientId = 2; + string serviceId = 3; + Circuit circuit = 4; +} + +message ListSessionsRequest{} +message ListSessionsResponse { + repeated Session sessions = 1; +} + +message RemoveSessionRequest { + string sessionId = 1; + bool now = 2; +} + +// +// --- Streams ------------------------------------------------------------------------------------------------------ // +// + +message StreamMetricsRequest { + repeated MetricMatcher matchers = 1; + + message MetricMatcher { + string nameRegex = 1; + string sourceIDRegex = 2; + } +} + +message StreamMetricsEvent { + string sourceId = 1; + google.protobuf.Timestamp timestamp = 2; + map tags = 3; + + map intMetrics = 4; + map floatMetrics = 5; + + repeated IntervalMetric intervalMetrics = 6; + + message IntervalMetric { + string name = 1; + google.protobuf.Timestamp intervalStartUTC = 2; + google.protobuf.Timestamp intervalEndUTC = 3; + map values = 4; + } +} + +message StreamSessionsRequest {} + +enum StreamSessionEventType { + SessionCreated = 0; + SessionDeleted = 1; + SessionPresent = 2; + CircuitUpdated = 3; +} + +message StreamSessionsEvent { + StreamSessionEventType eventType = 1; + string sessionId = 2; + string clientId = 3; + string serviceId = 4; + Circuit circuit = 5; +} + +message ToggleSessionTracesRequest { + bool enable = 1; + string serviceRegex = 2; + string clientRegex = 3; +} + +enum TraceFilterType { + EXCLUDE = 0; + INCLUDE = 1; +} + +message StreamTracesRequest { + bool enabledFilter = 1; + TraceFilterType filterType = 2; + repeated int32 contentTypes = 3; +} + +message InspectRequest { + string appRegex = 1; + repeated string requestedValues = 2; +} + +message InspectResponse { + bool success = 1; + repeated string errors = 2; + repeated InspectValue values = 3; + + message InspectValue { + string appId = 1; + string name = 2; + string value = 3; + } +} \ No newline at end of file diff --git a/fabric/router/config.go b/fabric/router/config.go new file mode 100644 index 000000000..4a69df4ff --- /dev/null +++ b/fabric/router/config.go @@ -0,0 +1,283 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/config" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "bytes" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/spf13/pflag" + "gopkg.in/yaml.v2" + "io/ioutil" + "time" +) + +const ( + FlagsCfgMapKey = "@flags" +) + +func LoadConfigMap(path string) (map[interface{}]interface{}, error) { + yamlBytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + cfgmap := make(map[interface{}]interface{}) + if err = yaml.NewDecoder(bytes.NewReader(yamlBytes)).Decode(&cfgmap); err != nil { + return nil, err + } + + config.InjectEnv(cfgmap) + + return cfgmap, nil +} + +func SetConfigMapFlags(cfgmap map[interface{}]interface{}, flags map[string]*pflag.Flag) { + cfgmap[FlagsCfgMapKey] = flags +} + +type Config struct { + Id *identity.TokenId + Forwarder *forwarder.Options + Trace struct { + Handler *channel2.TraceHandler + } + Profile struct { + Memory struct { + Path string + Interval time.Duration + } + CPU struct { + Path string + } + } + Ctrl struct { + Endpoint transport.Address + Options *channel2.Options + } + Link struct { + Listener transport.Address + Advertise transport.Address + Options *channel2.Options + } + Dialers map[string]xgress.XgressOptionsData + Listeners []listenerBinding + src map[interface{}]interface{} +} + +func (config *Config) Configure(sub config.Subconfig) error { + return sub.LoadConfig(config.src) +} + +func (config *Config) SetFlags(flags map[string]*pflag.Flag) { + SetConfigMapFlags(config.src, flags) +} + +func LoadConfig(path string) (*Config, error) { + cfgmap, err := LoadConfigMap(path) + + if err != nil { + return nil, err + } + + if value, found := cfgmap["v"]; found { + if value.(int) != 2 { + panic("config version mismatch: see docs for information on config updates") + } + } else { + panic("config version mismatch: no configuration version specified") + } + + identityConfig := identity.IdentityConfig{} + if value, found := cfgmap["identity"]; found { + submap := value.(map[interface{}]interface{}) + if value, found := submap["key"]; found { + identityConfig.Key = value.(string) + } + if value, found := submap["cert"]; found { + identityConfig.Cert = value.(string) + } + if value, found := submap["server_cert"]; found { + identityConfig.ServerCert = value.(string) + } + if value, found := submap["server_key"]; found { + identityConfig.ServerKey = value.(string) + } + if value, found := submap["ca"]; found { + identityConfig.CA = value.(string) + } + } + + cfg := &Config{src: cfgmap} + + if id, err := identity.LoadIdentity(identityConfig); err != nil { + return nil, fmt.Errorf("unable to load identity (%s)", err) + } else { + cfg.Id = identity.NewIdentity(id) + } + + cfg.Forwarder = forwarder.DefaultOptions() + if value, found := cfgmap["forwarder"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if options, err := forwarder.LoadOptions(submap); err == nil { + cfg.Forwarder = options + } else { + return nil, fmt.Errorf("invalid 'forwarder' stanza (%s)", err) + } + } else { + pfxlog.Logger().Warn("invalid or empty 'forwarder' stanza") + } + } + + if value, found := cfgmap["trace"]; found { + submap := value.(map[interface{}]interface{}) + if value, found := submap["path"]; found { + handler, err := channel2.NewTraceHandler(value.(string), cfg.Id) + if err != nil { + return nil, err + } + handler.AddDecoder(&channel2.Decoder{}) + handler.AddDecoder(&xgress.Decoder{}) + handler.AddDecoder(&ctrl_pb.Decoder{}) + cfg.Trace.Handler = handler + } + } + + if value, found := cfgmap["profile"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["memory"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["path"]; found { + cfg.Profile.Memory.Path = value.(string) + } + if value, found := submap["intervalMs"]; found { + cfg.Profile.Memory.Interval = time.Duration(value.(int)) * time.Millisecond + } else { + cfg.Profile.Memory.Interval = 15 * time.Second + } + } + } + if value, found := submap["cpu"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["path"]; found { + cfg.Profile.CPU.Path = value.(string) + } + } + } + } + } + + cfg.Ctrl.Options = channel2.DefaultOptions() + if value, found := cfgmap["ctrl"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["endpoint"]; found { + address, err := transport.ParseAddress(value.(string)) + if err != nil { + return nil, fmt.Errorf("cannot parse [ctrl/endpoint] (%s)", err) + } + cfg.Ctrl.Endpoint = address + } + if value, found := submap["options"]; found { + if optionsMap, ok := value.(map[interface{}]interface{}); ok { + cfg.Ctrl.Options = channel2.LoadOptions(optionsMap) + } + } + if cfg.Trace.Handler != nil { + cfg.Ctrl.Options.PeekHandlers = append(cfg.Ctrl.Options.PeekHandlers, cfg.Trace.Handler) + } + } + } + + cfg.Link.Options = channel2.DefaultOptions() + if value, found := cfgmap["link"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["listener"]; found { + address, err := transport.ParseAddress(value.(string)) + if err != nil { + return nil, fmt.Errorf("cannot parse [link/listener] (%s)", err) + } + cfg.Link.Listener = address + cfg.Link.Advertise = address + } + if value, found := submap["advertise"]; found { + address, err := transport.ParseAddress(value.(string)) + if err != nil { + return nil, fmt.Errorf("cannot parse [link/advertise] (%s)", err) + } + cfg.Link.Advertise = address + } + if value, found := submap["options"]; found { + if optionsMap, ok := value.(map[interface{}]interface{}); ok { + cfg.Link.Options = channel2.LoadOptions(optionsMap) + } + } + if cfg.Trace.Handler != nil { + cfg.Link.Options.PeekHandlers = append(cfg.Link.Options.PeekHandlers, cfg.Trace.Handler) + } + } + } + + if value, found := cfgmap["listeners"]; found { + if subarr, ok := value.([]interface{}); ok { + for _, value := range subarr { + if submap, ok := value.(map[interface{}]interface{}); ok { + binding, found := submap["binding"].(string) + if !found { + return nil, fmt.Errorf("[listener] must provide [binding] (%v)", submap) + } + _, found = submap["address"] + if !found { + return nil, fmt.Errorf("[listener] must provide [address] (%v)", submap) + } + cfg.Listeners = append(cfg.Listeners, listenerBinding{name: binding, options: submap}) + } + } + } + } + + if value, found := cfgmap["dialers"]; found { + if subarr, ok := value.([]interface{}); ok { + for _, value := range subarr { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["binding"]; found { + binding := value.(string) + if cfg.Dialers == nil { + cfg.Dialers = make(map[string]xgress.XgressOptionsData) + } + cfg.Dialers[binding] = submap + } else { + return nil, fmt.Errorf("[dialer] must provide [binding] (%v)", submap) + } + } + } + } + } + + return cfg, nil +} + +type listenerBinding struct { + name string + options xgress.XgressOptionsData +} diff --git a/fabric/router/forwarder/forwarder.go b/fabric/router/forwarder/forwarder.go new file mode 100644 index 000000000..31c6b9903 --- /dev/null +++ b/fabric/router/forwarder/forwarder.go @@ -0,0 +1,234 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package forwarder + +import ( + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/info" + "errors" + "github.com/michaelquigley/pfxlog" + "time" +) + +type Forwarder struct { + sessions *sessionTable + destinations *destinationTable + payloadBufferController *xgress.PayloadBufferController + metricsRegistry metrics.Registry + traceController trace.Controller +} + +type Destination interface { + SendPayload(payload *xgress.Payload) error + SendAcknowledgement(acknowledgement *xgress.Acknowledgement) error +} + +type XgressDestination interface { + Destination + Close() + Start() + IsTerminator() bool + Label() string +} + +func NewForwarder(metricsRegistry metrics.Registry) *Forwarder { + forwarder := &Forwarder{ + sessions: newSessionTable(), + destinations: newDestinationTable(), + metricsRegistry: metricsRegistry, + traceController: trace.NewController(), + } + + forwarder.payloadBufferController = xgress.NewPayloadBufferController(forwarder) + return forwarder +} + +func (forwarder *Forwarder) PayloadBuffer(sessionId *identity.TokenId, address xgress.Address) *xgress.PayloadBuffer { + return forwarder.payloadBufferController.BufferForSession(sessionId, address) +} + +func (forwarder *Forwarder) PayloadBufferController() *xgress.PayloadBufferController { + return forwarder.payloadBufferController +} + +func (forwarder *Forwarder) MetricsRegistry() metrics.Registry { + return forwarder.metricsRegistry +} + +func (forwarder *Forwarder) TraceController() trace.Controller { + return forwarder.traceController +} + +func (forwarder *Forwarder) RegisterDestination(sessionId *identity.TokenId, address xgress.Address, destination Destination) { + forwarder.destinations.addDestination(address, destination) + forwarder.destinations.linkDestinationToSession(sessionId, address) +} + +func (forwarder *Forwarder) UnregisterDestinations(sessionId *identity.TokenId) { + if addresses, found := forwarder.destinations.getAddressesForSession(sessionId); found { + for _, address := range addresses { + if destination, found := forwarder.destinations.getDestination(address); found { + forwarder.destinations.removeDestination(address) + destination.(XgressDestination).Close() + } + } + forwarder.destinations.unlinkSession(sessionId) + } +} + +func (forwarder *Forwarder) StartDestinations(sessionId *identity.TokenId) { + if addresses, found := forwarder.destinations.getAddressesForSession(sessionId); found { + for _, address := range addresses { + if destination, found := forwarder.destinations.getDestination(address); found { + if xgressDest, ok := destination.(XgressDestination); ok && xgressDest.IsTerminator() { + xgressDest.Start() + pfxlog.Logger().Infof("Started xgress for session %v", sessionId.Token) + } + } + } + } +} + +func (forwarder *Forwarder) HasDestination(address xgress.Address) bool { + _, found := forwarder.destinations.getDestination(address) + return found +} + +func (forwarder *Forwarder) RegisterLink(link *Link) { + forwarder.destinations.addDestination(xgress.Address(link.Id.Token), link) +} + +func (forwarder *Forwarder) UnregisterLink(link *Link) { + forwarder.destinations.removeDestination(xgress.Address(link.Id.Token)) +} + +func (forwarder *Forwarder) Route(route *ctrl_pb.Route) { + sessionId := &identity.TokenId{Token: route.SessionId} + var sessionFt *forwardTable + if ft, found := forwarder.sessions.getForwardTable(sessionId); found { + sessionFt = ft + } else { + sessionFt = newForwardTable() + } + for _, forward := range route.Forwards { + sessionFt.setForwardAddress(xgress.Address(forward.SrcAddress), xgress.Address(forward.DstAddress)) + } + forwarder.sessions.setForwardTable(sessionId, sessionFt) +} + +func (forwarder *Forwarder) Unroute(sessionId *identity.TokenId, now bool) { + if now { + forwarder.sessions.removeForwardTable(sessionId) + _ = forwarder.EndSession(sessionId) + } else { + go forwarder.unrouteTimeout(sessionId, 5000) + } +} + +func (forwarder *Forwarder) EndSession(sessionId *identity.TokenId) error { + forwarder.UnregisterDestinations(sessionId) + forwarder.payloadBufferController.EndSession(sessionId) + return nil +} + +func (forwarder *Forwarder) ForwardPayload(srcAddr xgress.Address, payload *xgress.Payload) error { + log := pfxlog.ContextLogger(string(srcAddr)) + + sessionId := &identity.TokenId{Token: payload.GetSessionId()} + if forwardTable, found := forwarder.sessions.getForwardTable(sessionId); found { + if dstAddr, found := forwardTable.getForwardAddress(srcAddr); found { + if dst, found := forwarder.destinations.getDestination(dstAddr); found { + if err := dst.SendPayload(payload); err != nil { + return err + } + log.WithFields(payload.GetLoggerFields()).Debugf("=> %s", string(dstAddr)) + forwardTable.lastUsed = info.NowInMilliseconds() + return nil + + } else { + return errors.New("no destination") + } + + } else { + return errors.New("no destination address") + } + + } else { + return errors.New("no forward table") + } +} + +func (forwarder *Forwarder) ForwardAcknowledgement(srcAddr xgress.Address, acknowledgement *xgress.Acknowledgement) error { + log := pfxlog.ContextLogger(string(srcAddr)) + + sessionId := &identity.TokenId{Token: acknowledgement.SessionId} + if forwardTable, found := forwarder.sessions.getForwardTable(sessionId); found { + if dstAddr, found := forwardTable.getForwardAddress(srcAddr); found { + if dst, found := forwarder.destinations.getDestination(dstAddr); found { + if err := dst.SendAcknowledgement(acknowledgement); err != nil { + return err + } + log.Debugf("=> %s", string(dstAddr)) + forwardTable.lastUsed = info.NowInMilliseconds() + return nil + + } else { + return errors.New("no destination") + } + + } else { + return errors.New("no destination address") + } + + } else { + return errors.New("no forward table") + } +} + +func (forwarder *Forwarder) Debug() string { + return forwarder.sessions.debug() + forwarder.destinations.debug() +} + +// unrouteTimeout implements a goroutine to manage route timeout processing. Once a timeout processor has been launched +// for a session, it will be checked repeatedly, looking to see if the session has crossed the inactivity threshold. +// Once it crosses the inactivity threshold, it gets removed. +// +func (forwarder *Forwarder) unrouteTimeout(sessionId *identity.TokenId, ms int64) { + log := pfxlog.ContextLogger("s/" + sessionId.Token) + log.Info("scheduled") + defer log.Warn("timeout") + + for { + time.Sleep(time.Duration(ms) * time.Millisecond) + + if ft, found := forwarder.sessions.getForwardTable(sessionId); found { + elapsedDelta := info.NowInMilliseconds() - ft.lastUsed + if elapsedDelta >= ms { + forwarder.sessions.removeForwardTable(sessionId) + _ = forwarder.EndSession(sessionId) + return + } + + } else { + return + } + } +} \ No newline at end of file diff --git a/fabric/router/forwarder/link.go b/fabric/router/forwarder/link.go new file mode 100644 index 000000000..998b1983c --- /dev/null +++ b/fabric/router/forwarder/link.go @@ -0,0 +1,46 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package forwarder + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type Link struct { + Id *identity.TokenId + Channel channel2.Channel +} + +func NewLink(id *identity.TokenId, channel channel2.Channel) *Link { + link := &Link{ + Id: id, + Channel: channel, + } + return link +} + +func (link *Link) SendPayload(payload *xgress.Payload) error { + msg := payload.Marshall() + return link.Channel.Send(msg) +} + +func (link *Link) SendAcknowledgement(acknowledgement *xgress.Acknowledgement) error { + msg := acknowledgement.Marshall() + return link.Channel.SendWithPriority(msg, channel2.Highest) +} diff --git a/fabric/router/forwarder/options.go b/fabric/router/forwarder/options.go new file mode 100644 index 000000000..1faa3dabf --- /dev/null +++ b/fabric/router/forwarder/options.go @@ -0,0 +1,44 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package forwarder + +import ( + "errors" + "time" +) + +type Options struct { + LatencyProbeInterval time.Duration +} + +func DefaultOptions() *Options { + return &Options{LatencyProbeInterval: time.Duration(10) * time.Second} +} + +func LoadOptions(src map[interface{}]interface{}) (*Options, error) { + options := DefaultOptions() + + if value, found := src["latencyProbeInterval"]; found { + if latencyProbeInterval, ok := value.(int); ok { + options.LatencyProbeInterval = time.Duration(latencyProbeInterval) * time.Millisecond + } else { + return nil, errors.New("invalid value for 'latencyProbeInterval'") + } + } + + return options, nil +} \ No newline at end of file diff --git a/fabric/router/forwarder/tables.go b/fabric/router/forwarder/tables.go new file mode 100644 index 000000000..49b907226 --- /dev/null +++ b/fabric/router/forwarder/tables.go @@ -0,0 +1,167 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package forwarder + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/info" + "fmt" + "github.com/orcaman/concurrent-map" + "reflect" +) + +// sessionTable implements a directory of forwardTables, keyed by sessionId. +// +type sessionTable struct { + sessions cmap.ConcurrentMap // map[string]*forwardTable +} + +func newSessionTable() *sessionTable { + return &sessionTable{ + sessions: cmap.New(), + } +} + +func (st *sessionTable) setForwardTable(sessionId *identity.TokenId, ft *forwardTable) { + st.sessions.Set(sessionId.Token, ft) +} + +func (st *sessionTable) getForwardTable(sessionId *identity.TokenId) (*forwardTable, bool) { + if ft, found := st.sessions.Get(sessionId.Token); found { + return ft.(*forwardTable), true + } + return nil, false +} + +func (st *sessionTable) removeForwardTable(sessionId *identity.TokenId) { + st.sessions.Remove(sessionId.Token) +} + +func (st *sessionTable) debug() string { + out := fmt.Sprintf("sessions (%d):\n", st.sessions.Count()) + for i := range st.sessions.IterBuffered() { + out += "\n" + out += fmt.Sprintf("\ts/%s", i.Key) + out += i.Val.(*forwardTable).debug() + } + return out +} + +// forwardTable implements a directory of destinations, keyed by source address. +// +type forwardTable struct { + lastUsed int64 + destinations cmap.ConcurrentMap // map[string]string +} + +func newForwardTable() *forwardTable { + return &forwardTable{ + lastUsed: info.NowInMilliseconds(), + destinations: cmap.New(), + } +} + +func (ft *forwardTable) setForwardAddress(src, dst xgress.Address) { + ft.destinations.Set(string(src), string(dst)) +} + +func (ft *forwardTable) getForwardAddress(src xgress.Address) (xgress.Address, bool) { + if dst, found := ft.destinations.Get(string(src)); found { + return xgress.Address(dst.(string)), true + } + return "", false +} + +func (ft *forwardTable) debug() string { + now := info.NowInMilliseconds() + out := fmt.Sprintf(" (%d ms):\n", now-ft.lastUsed) + for i := range ft.destinations.IterBuffered() { + out += fmt.Sprintf("\t\t@/%s -> @/%s\n", i.Key, i.Val) + } + return out +} + +// destinationTable implements a directory of destinations, keyed by Address. +// +type destinationTable struct { + destinations cmap.ConcurrentMap // map[xgress.Address]Destination + xgress cmap.ConcurrentMap // map[sessionId][]xgress.Address +} + +func newDestinationTable() *destinationTable { + return &destinationTable{ + destinations: cmap.New(), + xgress: cmap.New(), + } +} + +func (dt *destinationTable) addDestination(addr xgress.Address, destination Destination) { + dt.destinations.Set(string(addr), destination) +} + +func (dt *destinationTable) getDestination(addr xgress.Address) (Destination, bool) { + if dst, found := dt.destinations.Get(string(addr)); found { + return dst.(Destination), true + } + return nil, false +} + +func (dt *destinationTable) removeDestination(addr xgress.Address) { + dt.destinations.Remove(string(addr)) +} + +func (dt *destinationTable) linkDestinationToSession(sessionId *identity.TokenId, address xgress.Address) { + var addresses []xgress.Address + if i, found := dt.xgress.Get(sessionId.Token); found { + addresses = i.([]xgress.Address) + } else { + addresses = make([]xgress.Address, 0) + } + addresses = append(addresses, address) + dt.xgress.Set(sessionId.Token, addresses) +} + +func (dt *destinationTable) getAddressesForSession(sessionId *identity.TokenId) ([]xgress.Address, bool) { + if addresses, found := dt.xgress.Get(sessionId.Token); found { + return addresses.([]xgress.Address), found + } + return nil, false +} + +func (dt *destinationTable) unlinkSession(sessionId *identity.TokenId) { + dt.xgress.Remove(sessionId.Token) +} + +func (dt *destinationTable) debug() string { + out := fmt.Sprintf("\ndestinations (%d):\n\n", dt.destinations.Count()) + for i := range dt.destinations.IterBuffered() { + out += fmt.Sprintf("\t@/%s -> (%s (%p))\n", i.Key, reflect.TypeOf(i.Val.(Destination)).String(), i.Val) + } + out += "\n" + + out += fmt.Sprintf("xgress (%d):\n\n", dt.xgress.Count()) + for i := range dt.xgress.IterBuffered() { + out += fmt.Sprintf("\ts/%s:\n", i.Key) + addresses := i.Val.([]xgress.Address) + for _, address := range addresses { + out += fmt.Sprintf("\t\t@/%s\n", address) + } + } + out += "\n" + return out +} diff --git a/fabric/router/handler_ctrl/bind.go b/fabric/router/handler_ctrl/bind.go new file mode 100644 index 000000000..13b4d26bd --- /dev/null +++ b/fabric/router/handler_ctrl/bind.go @@ -0,0 +1,76 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type bindHandler struct { + id *identity.TokenId + dialerCfg map[string]xgress.XgressOptionsData + linkOptions *channel2.Options + forwarderOptions *forwarder.Options + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder + xctrls []xctrl.Xctrl + metricsRegistry metrics.Registry +} + +func NewBindHandler(id *identity.TokenId, + dialerCfg map[string]xgress.XgressOptionsData, + linkOptions *channel2.Options, + forwarderOptions *forwarder.Options, + ctrl xgress.CtrlChannel, + forwarder *forwarder.Forwarder, + xctrls []xctrl.Xctrl, + metricsRegistry metrics.Registry) channel2.BindHandler { + return &bindHandler{ + id: id, + dialerCfg: dialerCfg, + linkOptions: linkOptions, + forwarderOptions: forwarderOptions, + ctrl: ctrl, + forwarder: forwarder, + xctrls: xctrls, + metricsRegistry: metricsRegistry, + } +} + +func (bindHandler *bindHandler) BindChannel(ch channel2.Channel) error { + ch.AddReceiveHandler(newDialHandler(bindHandler.id, bindHandler.ctrl, bindHandler.linkOptions, bindHandler.forwarderOptions, bindHandler.forwarder, bindHandler.metricsRegistry)) + ch.AddReceiveHandler(newRouteHandler(bindHandler.id, bindHandler.ctrl, bindHandler.dialerCfg, bindHandler.forwarder)) + ch.AddReceiveHandler(newUnrouteHandler(bindHandler.forwarder)) + ch.AddReceiveHandler(newStartXgressHandler(bindHandler.forwarder)) + ch.AddReceiveHandler(newTraceHandler(bindHandler.id, bindHandler.forwarder.TraceController())) + ch.AddReceiveHandler(newInspectHandler(bindHandler.id)) + ch.AddPeekHandler(trace.NewChannelPeekHandler(bindHandler.id, ch, bindHandler.forwarder.TraceController(), trace.NewChannelSink(ch))) + + for _, x := range bindHandler.xctrls { + if err := ch.Bind(x); err != nil { + return err + } + } + + return nil +} diff --git a/fabric/router/handler_ctrl/dial.go b/fabric/router/handler_ctrl/dial.go new file mode 100644 index 000000000..590076fd3 --- /dev/null +++ b/fabric/router/handler_ctrl/dial.go @@ -0,0 +1,117 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/router/handler_link" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type dialHandler struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + linkOptions *channel2.Options + forwarderOptions *forwarder.Options + forwarder *forwarder.Forwarder + metricsRegistry metrics.Registry +} + +func newDialHandler(id *identity.TokenId, ctrl xgress.CtrlChannel, linkOptions *channel2.Options, forwarderOptions *forwarder.Options, forwarder *forwarder.Forwarder, metricsRegistry metrics.Registry) *dialHandler { + return &dialHandler{ + id: id, + ctrl: ctrl, + linkOptions: linkOptions, + forwarderOptions: forwarderOptions, + forwarder: forwarder, + metricsRegistry: metricsRegistry, + } +} + +func (h *dialHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_DialType) +} + +func (h *dialHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + log.Info("received link connect request") + + dial := &ctrl_pb.Dial{} + if err := proto.Unmarshal(msg.Body, dial); err == nil { + address, err := transport.ParseAddress(dial.Address) + if err == nil { + linkId := h.id.ShallowCloneWithNewToken(dial.Id) + name := "l/" + linkId.Token + + dialer := channel2.NewClassicDialer(linkId, address, nil) + ch, err := channel2.NewChannel(name, dialer, h.linkOptions) + if err == nil { + link := forwarder.NewLink(linkId, ch) + if err := link.Channel.Bind(handler_link.NewBindHandler(h.id, link, h.ctrl, h.forwarder)); err == nil { + h.forwarder.RegisterLink(link) + + go metrics.ProbeLatency( + link.Channel, + h.metricsRegistry.Histogram("link."+linkId.Token+".latency"), + h.forwarderOptions.LatencyProbeInterval, + ) + + linkMsg := &ctrl_pb.Link{Id: link.Id.Token} + body, err := proto.Marshal(linkMsg) + if err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_LinkType), body) + if err := h.ctrl.Channel().Send(msg); err == nil { + log.Infof("link [l/%s] up", link.Id.Token) + } else { + log.Errorf("unexpected error sending link (%s)", err) + } + + } else { + log.Errorf("unexpected error (%s)", err) + } + } else { + log.Errorf("error binding link (%s)", err) + } + } else { + log.Errorf("link dialing failed [%s]", address.String()) + + fault := &ctrl_pb.Fault{Subject: ctrl_pb.FaultSubject_LinkFault, Id: linkId.Token} + body, err := proto.Marshal(fault) + if err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_FaultType), body) + if err := h.ctrl.Channel().Send(msg); err != nil { + log.Errorf("error sending fault (%s)", err) + } + } else { + log.Errorf("unexpected error (%s)", err) + } + } + } else { + log.Errorf("link address parsing failed (%s)", err) + } + + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/router/handler_ctrl/inspect.go b/fabric/router/handler_ctrl/inspect.go new file mode 100644 index 000000000..73563d184 --- /dev/null +++ b/fabric/router/handler_ctrl/inspect.go @@ -0,0 +1,104 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/debugz" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "strings" +) + +type inspectHandler struct { + id *identity.TokenId +} + +func newInspectHandler(id *identity.TokenId) *inspectHandler { + return &inspectHandler{id: id} +} + +func (*inspectHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_InspectRequestType) +} + +func (handler *inspectHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + context := &inspectRequestContext{ + handler: handler, + msg: msg, + ch: ch, + request: &ctrl_pb.InspectRequest{}, + response: &ctrl_pb.InspectResponse{Success: true}, + } + + var err error + if err = proto.Unmarshal(msg.Body, context.request); err != nil { + context.appendError(err.Error()) + } + + if !context.response.Success { + context.sendResponse() + return + } + + context.processLocal() + context.sendResponse() +} + +type inspectRequestContext struct { + handler *inspectHandler + msg *channel2.Message + ch channel2.Channel + request *ctrl_pb.InspectRequest + response *ctrl_pb.InspectResponse +} + +func (context *inspectRequestContext) processLocal() { + for _, requested := range context.request.RequestedValues { + if strings.ToLower(requested) == "stackdump" { + context.appendValue(context.handler.id, requested, debugz.GenerateStack()) + } + } +} + +func (context *inspectRequestContext) sendResponse() { + body, err := proto.Marshal(context.response) + if err != nil { + pfxlog.Logger().Errorf("unexpected error serializing InspectResponse (%s)", err) + return + } + + responseMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_InspectResponseType), body) + responseMsg.ReplyTo(context.msg) + if err := context.ch.Send(responseMsg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending InspectResponse (%s)", err) + } +} + +func (context *inspectRequestContext) appendValue(appId *identity.TokenId, name string, value string) { + context.response.Values = append(context.response.Values, &ctrl_pb.InspectResponse_InspectValue{ + Name: name, + Value: value, + }) +} + +func (context *inspectRequestContext) appendError(err string) { + context.response.Success = false + context.response.Errors = append(context.response.Errors, err) +} diff --git a/fabric/router/handler_ctrl/route.go b/fabric/router/handler_ctrl/route.go new file mode 100644 index 000000000..b96539a79 --- /dev/null +++ b/fabric/router/handler_ctrl/route.go @@ -0,0 +1,110 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/router/handler_xgress" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type routeHandler struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + dialerCfg map[string]xgress.XgressOptionsData + forwarder *forwarder.Forwarder +} + +func newRouteHandler(id *identity.TokenId, ctrl xgress.CtrlChannel, dialerCfg map[string]xgress.XgressOptionsData, forwarder *forwarder.Forwarder) *routeHandler { + return &routeHandler{ + id: id, + ctrl: ctrl, + dialerCfg: dialerCfg, + forwarder: forwarder, + } +} + +func (rh *routeHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_RouteType) +} + +func (rh *routeHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + route := &ctrl_pb.Route{} + if err := proto.Unmarshal(msg.Body, route); err == nil { + if err := rh.createRoute(route); err == nil { + response := channel2.NewResult(true, "") + response.ReplyTo(msg) + if err := rh.ctrl.Channel().Send(response); err == nil { + log.Infof("handled route for [s/%s]", route.SessionId) + } else { + log.Errorf("send response failed for [s/%s] (%s)", route.SessionId, err) + } + } else { + pfxlog.ContextLogger(ch.Label()).Errorf("error creating route for [s/%s] (%s)", route.SessionId, err) + } + + } else { + pfxlog.ContextLogger(ch.Label()).Errorf("error unmarshaling (%s)", err) + } +} + +func (rh *routeHandler) createRoute(route *ctrl_pb.Route) error { + if route.Egress != nil { + if rh.forwarder.HasDestination(xgress.Address(route.Egress.Address)) { + pfxlog.Logger().Warnf("destination exists for [%s]", route.Egress.Address) + } else { + if err := rh.connectEgress(route); err != nil { + return err + } + } + } + + rh.forwarder.Route(route) + + return nil +} + +func (rh *routeHandler) connectEgress(route *ctrl_pb.Route) error { + log := pfxlog.Logger().WithField("sessionId", route.SessionId) + log.Debugf("route request received. binding: %v, destination: %v, address: %v", + route.Egress.Binding, route.Egress.Destination, route.Egress.Address) + if factory, err := xgress.GlobalRegistry().Factory(route.Egress.Binding); err == nil { + if dialer, err := factory.CreateDialer(rh.dialerCfg[route.Egress.Binding]); err == nil { + sessionId := &identity.TokenId{Token: route.SessionId} + return dialer.Dial(route.Egress.Destination, + sessionId, + xgress.Address(route.Egress.Address), + handler_xgress.NewBindHandler( + handler_xgress.NewReceiveHandler(rh.ctrl, rh.forwarder), + handler_xgress.NewCloseHandler(rh.ctrl, rh.forwarder), + rh.forwarder)) + } else { + return fmt.Errorf("unable to create dialer (%s)", err) + } + + } else { + return err + } +} diff --git a/fabric/router/handler_ctrl/start_xgress.go b/fabric/router/handler_ctrl/start_xgress.go new file mode 100644 index 000000000..3b2367df1 --- /dev/null +++ b/fabric/router/handler_ctrl/start_xgress.go @@ -0,0 +1,44 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/michaelquigley/pfxlog" +) + +type startXgressHandler struct { + forwarder *forwarder.Forwarder +} + +func newStartXgressHandler(forwarder *forwarder.Forwarder) *startXgressHandler { + return &startXgressHandler{forwarder: forwarder} +} + +func (h *startXgressHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_StartXgressType) +} + +func (h *startXgressHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + token := string(msg.Body) + pfxlog.Logger().Infof("attempting to start xgress for session %v", token) + sessionId := &identity.TokenId{Token: token} + h.forwarder.StartDestinations(sessionId) +} diff --git a/fabric/router/handler_ctrl/toggle_pipe_traces.go b/fabric/router/handler_ctrl/toggle_pipe_traces.go new file mode 100644 index 000000000..e3b108cce --- /dev/null +++ b/fabric/router/handler_ctrl/toggle_pipe_traces.go @@ -0,0 +1,99 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-foundation/identity/identity" + trace_pb "github.com/netfoundry/ziti-foundation/trace/pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +func newTraceHandler(appId *identity.TokenId, controller trace.Controller) *traceHandler { + return &traceHandler{ + appId: appId, + controller: controller, + enabled: false, + } +} + +type traceHandler struct { + appId *identity.TokenId + controller trace.Controller + enabled bool +} + +func (*traceHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_TogglePipeTracesRequestType) +} + +func (handler *traceHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + request := &trace_pb.TogglePipeTracesRequest{} + + if err := proto.Unmarshal(msg.Body, request); err != nil { + sendFailure(msg, ch, err.Error()) + return + } + + matchers, result := trace.NewPipeToggleMatchers(request) + + if result.Success { + resultChan := make(chan trace.ToggleApplyResult) + + if matchers.AppMatcher.Matches(handler.appId.Token) { + if request.Enable { + handler.controller.EnableTracing(trace.SourceTypePipe, matchers.PipeMatcher, resultChan) + } else { + handler.controller.DisableTracing(trace.SourceTypePipe, matchers.PipeMatcher, resultChan) + } + } + + verbosity := trace.GetVerbosity(request.Verbosity) + for applyResult := range resultChan { + applyResult.Append(result, verbosity) + } + } + + if result.Success { + sendSuccess(msg, ch, result.Message.String()) + } else { + sendFailure(msg, ch, result.Message.String()) + } +} + +func sendSuccess(request *channel2.Message, ch channel2.Channel, message string) { + sendResult(request, ch, message, true) +} + +func sendFailure(request *channel2.Message, ch channel2.Channel, message string) { + sendResult(request, ch, message, false) +} + +func sendResult(request *channel2.Message, ch channel2.Channel, message string, success bool) { + log := pfxlog.ContextLogger(ch.Label()) + if !success { + log.Errorf("ctrl error (%s)", message) + } + + response := channel2.NewResult(success, message) + response.ReplyTo(request) + ch.Send(response) + log.Debug("success") +} \ No newline at end of file diff --git a/fabric/router/handler_ctrl/unroute.go b/fabric/router/handler_ctrl/unroute.go new file mode 100644 index 000000000..f2d2234a2 --- /dev/null +++ b/fabric/router/handler_ctrl/unroute.go @@ -0,0 +1,47 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_ctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type unrouteHandler struct { + forwarder *forwarder.Forwarder +} + +func newUnrouteHandler(forwarder *forwarder.Forwarder) *unrouteHandler { + return &unrouteHandler{forwarder: forwarder} +} + +func (h *unrouteHandler) ContentType() int32 { + return int32(ctrl_pb.ContentType_UnrouteType) +} + +func (h *unrouteHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + removeRoute := &ctrl_pb.Unroute{} + if err := proto.Unmarshal(msg.Body, removeRoute); err == nil { + h.forwarder.Unroute(&identity.TokenId{Token: removeRoute.SessionId}, removeRoute.Now) + } else { + pfxlog.ContextLogger(ch.Label()).Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/router/handler_link/accept.go b/fabric/router/handler_link/accept.go new file mode 100644 index 000000000..6e15b5b72 --- /dev/null +++ b/fabric/router/handler_link/accept.go @@ -0,0 +1,80 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/michaelquigley/pfxlog" +) + +type Accepter struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder + listener channel2.UnderlayListener + options *channel2.Options + forwarderOptions *forwarder.Options +} + +func NewAccepter(id *identity.TokenId, + ctrl xgress.CtrlChannel, + forwarder *forwarder.Forwarder, + listener channel2.UnderlayListener, + options *channel2.Options, + forwarderOptions *forwarder.Options) *Accepter { + return &Accepter{ + id: id, + ctrl: ctrl, + forwarder: forwarder, + listener: listener, + options: options, + forwarderOptions: forwarderOptions, + } +} + +func (accepter *Accepter) Run() { + log := pfxlog.Logger() + log.Info("started") + defer log.Warn("exited") + + for { + ch, err := channel2.NewChannel("link", accepter.listener, accepter.options) + if err == nil { + link := forwarder.NewLink(ch.Id(), ch) + + if err := link.Channel.Bind(NewBindHandler(accepter.id, link, accepter.ctrl, accepter.forwarder)); err == nil { + accepter.forwarder.RegisterLink(link) + + go metrics.ProbeLatency( + link.Channel, + accepter.forwarder.MetricsRegistry().Histogram("link."+link.Id.Token+".latency"), + accepter.forwarderOptions.LatencyProbeInterval, + ) + + log.Infof("accepted new link [l/%s]", link.Channel.Id().Token) + } else { + log.Infof("error binding new link (%s)", err) + } + } else { + log.Errorf("error accepting (%s)", err) + } + } +} diff --git a/fabric/router/handler_link/ack.go b/fabric/router/handler_link/ack.go new file mode 100644 index 000000000..d589c4fe4 --- /dev/null +++ b/fabric/router/handler_link/ack.go @@ -0,0 +1,50 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/michaelquigley/pfxlog" +) + +type ackHandler struct { + link *forwarder.Link + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func newAckHandler(link *forwarder.Link, ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *ackHandler { + return &ackHandler{link: link, ctrl: ctrl, forwarder: forwarder} +} + +func (ackHandler *ackHandler) ContentType() int32 { + return xgress.ContentTypeAcknowledgementType +} + +func (ackHandler *ackHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + if ack, err := xgress.UnmarshallAcknowledgement(msg); err == nil { + if err := ackHandler.forwarder.ForwardAcknowledgement(xgress.Address(ackHandler.link.Id.Token), ack); err != nil { + log.Debugf("unable to forward acknowledgement (%s)", err) + } + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/router/handler_link/bind.go b/fabric/router/handler_link/bind.go new file mode 100644 index 000000000..119aef746 --- /dev/null +++ b/fabric/router/handler_link/bind.go @@ -0,0 +1,50 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/trace" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type bindHandler struct { + id *identity.TokenId + link *forwarder.Link + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func NewBindHandler(id *identity.TokenId, link *forwarder.Link, ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *bindHandler { + return &bindHandler{id: id, link: link, ctrl: ctrl, forwarder: forwarder} +} + +func (bindHandler *bindHandler) BindChannel(ch channel2.Channel) error { + ch.SetLogicalName("l/" + bindHandler.link.Id.Token) + ch.SetUserData(bindHandler.link.Id.Token) + ch.AddCloseHandler(newCloseHandler(bindHandler.link, bindHandler.ctrl, bindHandler.forwarder)) + ch.AddErrorHandler(newErrorHandler(bindHandler.link, bindHandler.ctrl)) + ch.AddReceiveHandler(newPayloadHandler(bindHandler.link, bindHandler.ctrl, bindHandler.forwarder)) + ch.AddReceiveHandler(newAckHandler(bindHandler.link, bindHandler.ctrl, bindHandler.forwarder)) + ch.AddReceiveHandler(&channel2.LatencyHandler{}) + ch.AddPeekHandler(metrics.NewChannelPeekHandler(bindHandler.link.Id.Token, bindHandler.forwarder.MetricsRegistry())) + ch.AddPeekHandler(trace.NewChannelPeekHandler(bindHandler.link.Id, ch, bindHandler.forwarder.TraceController(), trace.NewChannelSink(bindHandler.ctrl.Channel()))) + return nil +} diff --git a/fabric/router/handler_link/close.go b/fabric/router/handler_link/close.go new file mode 100644 index 000000000..249521e25 --- /dev/null +++ b/fabric/router/handler_link/close.go @@ -0,0 +1,55 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type closeHandler struct { + link *forwarder.Link + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func newCloseHandler(link *forwarder.Link, ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *closeHandler { + return &closeHandler{link: link, ctrl: ctrl, forwarder: forwarder} +} + +func (h *closeHandler) HandleClose(ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + log.Info("link closed") + + fault := &ctrl_pb.Fault{Subject: ctrl_pb.FaultSubject_LinkFault, Id: h.link.Id.Token} + if body, err := proto.Marshal(fault); err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_FaultType), body) + if err := h.ctrl.Channel().Send(msg); err == nil { + log.Error("transmitted link fault") + } else { + log.Errorf("unexpected error transmitting link fault (%s)", err) + } + } else { + log.Errorf("unexpected error (%s)", err) + } + + h.forwarder.UnregisterLink(h.link) +} diff --git a/fabric/router/handler_link/error.go b/fabric/router/handler_link/error.go new file mode 100644 index 000000000..352cd8c54 --- /dev/null +++ b/fabric/router/handler_link/error.go @@ -0,0 +1,52 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type errorHandler struct { + link *forwarder.Link + ctrl xgress.CtrlChannel +} + +func newErrorHandler(link *forwarder.Link, ctrl xgress.CtrlChannel) *errorHandler { + return &errorHandler{link: link, ctrl: ctrl} +} + +func (errorHandler *errorHandler) HandleError(err error, ch channel2.Channel) { + log := pfxlog.ContextLogger(errorHandler.link.Channel.Label()) + fault := &ctrl_pb.Fault{ + Subject: ctrl_pb.FaultSubject_LinkFault, + Id: errorHandler.link.Id.Token, + } + if body, err := proto.Marshal(fault); err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_FaultType), body) + if err := errorHandler.ctrl.Channel().Send(msg); err == nil { + log.Infof("transmitted link fault") + } else { + log.Errorf("unexpected error sending fault (%s)", err) + } + } + errorHandler.link.Channel.Close() +} diff --git a/fabric/router/handler_link/payload.go b/fabric/router/handler_link/payload.go new file mode 100644 index 000000000..c362694ff --- /dev/null +++ b/fabric/router/handler_link/payload.go @@ -0,0 +1,57 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_link + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/michaelquigley/pfxlog" +) + +type payloadHandler struct { + link *forwarder.Link + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func newPayloadHandler(link *forwarder.Link, ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *payloadHandler { + return &payloadHandler{link: link, ctrl: ctrl, forwarder: forwarder} +} + +func (h *payloadHandler) ContentType() int32 { + return xgress.ContentTypePayloadType +} + +func (h *payloadHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + log := pfxlog.ContextLogger(ch.Label()) + + payload, err := xgress.UnmarshallPayload(msg) + if err == nil { + if err := h.forwarder.ForwardPayload(xgress.Address(h.link.Id.Token), payload); err != nil { + log.Debugf("unable to forward (%s)", err) + } + if payload.IsSessionEndFlagSet() { + if err := h.forwarder.EndSession(&identity.TokenId{Token: payload.GetSessionId()}); err != nil { + pfxlog.ContextLogger(ch.Label()).Errorf("failed to end session [s/%s] (%s)", payload.GetSessionId(), err) + } + } + } else { + log.Errorf("unexpected error (%s)", err) + } +} diff --git a/fabric/router/handler_xgress/bind.go b/fabric/router/handler_xgress/bind.go new file mode 100644 index 000000000..e7798f10f --- /dev/null +++ b/fabric/router/handler_xgress/bind.go @@ -0,0 +1,54 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_xgress + +import ( + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type bindHandler struct { + receiveHandler xgress.ReceiveHandler + closeHandler xgress.CloseHandler + metricsPeekHandler xgress.PeekHandler + forwarder *forwarder.Forwarder +} + +func NewBindHandler(receiveHandler xgress.ReceiveHandler, closeHandler xgress.CloseHandler, forwarder *forwarder.Forwarder) *bindHandler { + return &bindHandler{ + receiveHandler: receiveHandler, + closeHandler: closeHandler, + metricsPeekHandler: metrics.NewXgressPeekHandler(forwarder.MetricsRegistry()), + forwarder: forwarder, + } +} + +func (bindHandler *bindHandler) HandleXgressBind(sessionId *identity.TokenId, address xgress.Address, originator xgress.Originator, x *xgress.Xgress) { + x.SetReceiveHandler(bindHandler.receiveHandler) + x.AddPeekHandler(bindHandler.metricsPeekHandler) + + payloadBuffer := bindHandler.forwarder.PayloadBuffer(sessionId, address) + payloadBuffer.Originator = originator + payloadBuffer.SrcAddress = address + x.SetPayloadBuffer(payloadBuffer) + + x.SetCloseHandler(bindHandler.closeHandler) + + bindHandler.forwarder.RegisterDestination(sessionId, x.Address(), x) +} diff --git a/fabric/router/handler_xgress/close.go b/fabric/router/handler_xgress/close.go new file mode 100644 index 000000000..bd2349d49 --- /dev/null +++ b/fabric/router/handler_xgress/close.go @@ -0,0 +1,70 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_xgress + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +type closeHandler struct { + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func NewCloseHandler(ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *closeHandler { + return &closeHandler{ctrl: ctrl, forwarder: forwarder} +} + +func (txc *closeHandler) HandleXgressClose(x *xgress.Xgress) { + log := pfxlog.ContextLogger(x.Label()) + log.Info("running") + defer log.Info("complete") + + // Send end of session payload + log.Debug("sending end of session payload") + if err := txc.forwarder.ForwardPayload(x.Address(), x.GetEndSession()); err != nil { + log.Errorf("error forwarding end session payload (%s)", err) + } + + // Notify the forwarder that the session is ending + log.Debug("removing session from forwarder") + if err := txc.forwarder.EndSession(x.SessionId()); err != nil { + log.Errorf("error ending forwarder session (%s)", err) + } + + // Notify the controller of the xgress fault + fault := &ctrl_pb.Fault{Id: x.SessionId().Token} + if x.Originator() == xgress.Initiator { + fault.Subject = ctrl_pb.FaultSubject_IngressFault + } else if x.Originator() == xgress.Terminator { + fault.Subject = ctrl_pb.FaultSubject_EgressFault + } + if body, err := proto.Marshal(fault); err == nil { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_FaultType), body) + log.Debug("notifying controller of fault") + if err := txc.ctrl.Channel().Send(msg); err != nil { + log.Errorf("error sending fault (%s)", err) + } + } else { + log.Errorf("error marshalling (%s)", err) + } +} diff --git a/fabric/router/handler_xgress/receive.go b/fabric/router/handler_xgress/receive.go new file mode 100644 index 000000000..52aff1dfa --- /dev/null +++ b/fabric/router/handler_xgress/receive.go @@ -0,0 +1,38 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package handler_xgress + +import ( + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/michaelquigley/pfxlog" +) + +type receiveHandler struct { + ctrl xgress.CtrlChannel + forwarder *forwarder.Forwarder +} + +func NewReceiveHandler(ctrl xgress.CtrlChannel, forwarder *forwarder.Forwarder) *receiveHandler { + return &receiveHandler{ctrl: ctrl, forwarder: forwarder} +} + +func (xrh *receiveHandler) HandleXgressReceive(payload *xgress.Payload, x *xgress.Xgress) { + if err := xrh.forwarder.ForwardPayload(x.Address(), payload); err != nil { + pfxlog.ContextLogger(x.Label()).WithFields(payload.GetLoggerFields()).Errorf("unable to forward (%s)", err) + } +} diff --git a/fabric/router/monitor.go b/fabric/router/monitor.go new file mode 100644 index 000000000..d2bdcc24a --- /dev/null +++ b/fabric/router/monitor.go @@ -0,0 +1,21 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +type RouterMonitor interface { + Monitor() +} diff --git a/fabric/router/monitor_darwin.go b/fabric/router/monitor_darwin.go new file mode 100644 index 000000000..4f90b717d --- /dev/null +++ b/fabric/router/monitor_darwin.go @@ -0,0 +1,42 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +import ( + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/michaelquigley/pfxlog" + "os" + "os/signal" + "syscall" +) + +type routerMonitor struct { + forwarder *forwarder.Forwarder +} + +func newRouterMonitor(forwarder *forwarder.Forwarder) *routerMonitor { + return &routerMonitor{forwarder: forwarder} +} + +func (routerMonitor *routerMonitor) Monitor() { + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, syscall.SIGUSR1) + for { + <-signalChan + pfxlog.Logger().Info("\n" + routerMonitor.forwarder.Debug()) + } +} diff --git a/fabric/router/monitor_linux.go b/fabric/router/monitor_linux.go new file mode 100644 index 000000000..4f90b717d --- /dev/null +++ b/fabric/router/monitor_linux.go @@ -0,0 +1,42 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +import ( + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/michaelquigley/pfxlog" + "os" + "os/signal" + "syscall" +) + +type routerMonitor struct { + forwarder *forwarder.Forwarder +} + +func newRouterMonitor(forwarder *forwarder.Forwarder) *routerMonitor { + return &routerMonitor{forwarder: forwarder} +} + +func (routerMonitor *routerMonitor) Monitor() { + signalChan := make(chan os.Signal, 1) + signal.Notify(signalChan, syscall.SIGUSR1) + for { + <-signalChan + pfxlog.Logger().Info("\n" + routerMonitor.forwarder.Debug()) + } +} diff --git a/fabric/router/monitor_windows.go b/fabric/router/monitor_windows.go new file mode 100644 index 000000000..f5671a9f0 --- /dev/null +++ b/fabric/router/monitor_windows.go @@ -0,0 +1,34 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +import ( + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "time" +) + +type routerMonitor struct{} + +func newRouterMonitor(forwarder *forwarder.Forwarder) *routerMonitor { + return &routerMonitor{} +} + +func (routerMonitor *routerMonitor) Monitor() { + for { + time.Sleep(24 * time.Hour) + } +} diff --git a/fabric/router/router.go b/fabric/router/router.go new file mode 100644 index 000000000..950fdd224 --- /dev/null +++ b/fabric/router/router.go @@ -0,0 +1,215 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package router + +import ( + "github.com/netfoundry/ziti-fabric/fabric/metrics" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/router/forwarder" + "github.com/netfoundry/ziti-fabric/fabric/router/handler_ctrl" + "github.com/netfoundry/ziti-fabric/fabric/router/handler_link" + "github.com/netfoundry/ziti-fabric/fabric/router/handler_xgress" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-fabric/fabric/xgress_proxy" + "github.com/netfoundry/ziti-fabric/fabric/xgress_transport" + "github.com/netfoundry/ziti-fabric/fabric/xgress_udp" + "github.com/netfoundry/ziti-foundation/profiler" + "encoding/json" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/util/info" + "github.com/sirupsen/logrus" + "math/rand" + "time" +) + +type Router struct { + config *Config + ctrl channel2.Channel + ctrlOptions *channel2.Options + linkOptions *channel2.Options + linkListener channel2.UnderlayListener + forwarder *forwarder.Forwarder + xctrls []xctrl.Xctrl + xctrlDone chan struct{} + metricsRegistry metrics.Registry +} + +func (router *Router) Channel() channel2.Channel { + return router.ctrl +} + +func Create(config *Config) *Router { + metricsRegistry := metrics.NewRegistry(ctrl_pb.MetricsSourceType_Internal, config.Id.Token, make(map[string]string), time.Second*15, nil) + + return &Router{ + config: config, + forwarder: forwarder.NewForwarder(metricsRegistry), + metricsRegistry: metricsRegistry, + } +} + +func (router *Router) RegisterXctrl(x xctrl.Xctrl) error { + if err := router.config.Configure(x); err != nil { + return err + } + if x.Enabled() { + router.xctrls = append(router.xctrls, x) + } + return nil +} + +func (r *Router) Run() error { + rand.Seed(info.NowInMilliseconds()) + + r.showOptions() + + r.startProfiling() + + if err := r.registerComponents(); err != nil { + return err + } + + r.instantiateListeners() + + r.startLinkListener() + + if err := r.startControlPlane(); err != nil { + return err + } + + for { + time.Sleep(1 * time.Hour) + } +} + +func (router *Router) showOptions() { + if ctrl, err := json.Marshal(router.config.Ctrl.Options); err == nil { + pfxlog.Logger().Infof("ctrl = %s", string(ctrl)) + } else { + logrus.Fatalf("unable to display options (%w)", err) + } + if link, err := json.Marshal(router.config.Link.Options); err == nil { + pfxlog.Logger().Infof("link = %s", string(link)) + } else { + logrus.Fatalf("unable to display options (%w)", err) + } +} + +func (router *Router) startProfiling() { + if router.config.Profile.Memory.Path != "" { + go profiler.NewMemory(router.config.Profile.Memory.Path, router.config.Profile.Memory.Interval).Run() + } + if router.config.Profile.CPU.Path != "" { + if cpu, err := profiler.NewCPU(router.config.Profile.CPU.Path); err == nil { + go cpu.Run() + } else { + pfxlog.Logger().Errorf("unexpected error launching cpu profiling (%s)", err) + } + } + go newRouterMonitor(router.forwarder).Monitor() +} + +func (router *Router) registerComponents() error { + xgress.GlobalRegistry().Register("proxy", xgress_proxy.NewFactory(router.config.Id, router)) + xgress.GlobalRegistry().Register("transport", xgress_transport.NewFactory(router.config.Id, router)) + xgress.GlobalRegistry().Register("udp", xgress_udp.NewFactory(router.config.Id, router)) + + return nil +} + +func (router *Router) instantiateListeners() { + for _, binding := range router.config.Listeners { + factory, err := xgress.GlobalRegistry().Factory(binding.name) + if err != nil { + logrus.Fatalf("error getting xgress factory [%s] (%s)", binding.name, err) + } + listener, err := factory.CreateListener(binding.options) + if err != nil { + logrus.Fatalf("error creating xgress listener [%s] (%s)", binding.name, err) + } + if address, found := binding.options["address"]; found { + err = listener.Listen(address.(string), + handler_xgress.NewBindHandler( + handler_xgress.NewReceiveHandler(router, router.forwarder), + handler_xgress.NewCloseHandler(router, router.forwarder), + router.forwarder, + ), + ) + if err != nil { + logrus.Fatalf("error listening [%s] (%s)", binding.name, err) + } + logrus.Infof("created xgress listener [%s] at [%s]", binding.name, address) + } + } +} + +func (router *Router) startLinkListener() { + if router.config.Link.Advertise != nil && router.config.Link.Listener != nil { + router.linkListener = channel2.NewClassicListener(router.config.Id, router.config.Link.Listener) + if err := router.linkListener.Listen(); err != nil { + panic(err) + } + linkAccepter := handler_link.NewAccepter(router.config.Id, router, router.forwarder, router.linkListener, router.config.Link.Options, router.config.Forwarder) + go linkAccepter.Run() + } else { + pfxlog.Logger().Warn("skipping link listener due to configuration") + } +} + +func (router *Router) startControlPlane() error { + var attributes map[int32][]byte + if router.config.Link.Listener != nil && router.config.Link.Advertise != nil { + attributes = make(map[int32][]byte) + attributes[channel2.HelloListenerHeader] = []byte(router.config.Link.Advertise.String()) + } + + dialer := channel2.NewReconnectingDialer(router.config.Id, router.config.Ctrl.Endpoint, attributes) + + bindHandler := handler_ctrl.NewBindHandler( + router.config.Id, + router.config.Dialers, + router.config.Link.Options, + router.config.Forwarder, + router, + router.forwarder, + router.xctrls, + router.metricsRegistry, + ) + + router.config.Ctrl.Options.BindHandlers = append(router.config.Ctrl.Options.BindHandlers, bindHandler) + + ch, err := channel2.NewChannel("ctrl", dialer, router.config.Ctrl.Options) + if err != nil { + return fmt.Errorf("error connecting ctrl (%s)", err) + } + + router.ctrl = ch + + router.xctrlDone = make(chan struct{}) + for _, x := range router.xctrls { + if err := x.Run(router.ctrl, nil, router.xctrlDone); err != nil { + return err + } + } + + router.metricsRegistry.EventController().AddHandler(metrics.NewChannelReporter(router.ctrl)) + + return nil +} diff --git a/fabric/trace/channel_peekhandler.go b/fabric/trace/channel_peekhandler.go new file mode 100644 index 000000000..d77120800 --- /dev/null +++ b/fabric/trace/channel_peekhandler.go @@ -0,0 +1,165 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package trace + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-fabric/fabric/pb/mgmt_pb" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + trace_pb "github.com/netfoundry/ziti-foundation/trace/pb" + "fmt" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "sync/atomic" + "time" +) + +var decoders = []channel2.TraceMessageDecoder{&channel2.Decoder{}, &ctrl_pb.Decoder{}, &xgress.Decoder{}, &mgmt_pb.Decoder{}} + +type ChannelPeekHandler struct { + appId *identity.TokenId + ch channel2.Channel + enabled int32 + controller Controller + decoders []channel2.TraceMessageDecoder + eventSink EventHandler +} + +func (handler *ChannelPeekHandler) EnableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + handler.ToggleTracing(sourceType, matcher, true, resultChan) +} + +func (handler *ChannelPeekHandler) DisableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + handler.ToggleTracing(sourceType, matcher, false, resultChan) +} + +func (handler *ChannelPeekHandler) ToggleTracing(sourceType SourceType, matcher SourceMatcher, enable bool, resultChan chan<- ToggleApplyResult) { + name := handler.ch.LogicalName() + matched := sourceType == SourceTypePipe && matcher.Matches(name) + prevState := handler.IsEnabled() + nextState := prevState + if matched { + handler.enable(enable) + nextState = enable + } + resultChan <- &ToggleApplyResultImpl{matched, + fmt.Sprintf("Link %v.%v matched? %v. Old trace state: %v, New trace state: %v", + handler.appId.Token, name, matched, prevState, nextState)} +} + +func NewChannelPeekHandler(appId *identity.TokenId, ch channel2.Channel, controller Controller, eventSink EventHandler) *ChannelPeekHandler { + + handler := &ChannelPeekHandler{ + appId: appId, + ch: ch, + enabled: 0, + controller: controller, + decoders: decoders, + eventSink: eventSink, + } + controller.AddSource(handler) + return handler +} + +func (handler *ChannelPeekHandler) enable(enabled bool) { + atomic.StoreInt32(&handler.enabled, btoi(enabled)) +} + +func btoi(val bool) int32 { + if val { + return 1 + } + return 0 +} + +func (handler *ChannelPeekHandler) IsEnabled() bool { + return atomic.LoadInt32(&handler.enabled) == 1 +} + +func (*ChannelPeekHandler) Connect(ch channel2.Channel, remoteAddress string) { +} + +func (handler *ChannelPeekHandler) Rx(msg *channel2.Message, ch channel2.Channel) { + handler.trace(msg, ch, false) +} + +func (handler *ChannelPeekHandler) Tx(msg *channel2.Message, ch channel2.Channel) { + handler.trace(msg, ch, true) +} + +func (handler *ChannelPeekHandler) Close(ch channel2.Channel) { + handler.controller.RemoveSource(handler) +} + +func (handler *ChannelPeekHandler) trace(msg *channel2.Message, ch channel2.Channel, rx bool) { + if !handler.IsEnabled() || msg.ContentType == int32(ctrl_pb.ContentType_TraceEventType) || + msg.ContentType == int32(mgmt_pb.ContentType_StreamTracesEventType) { + return + } + + var decode []byte + for _, decoder := range handler.decoders { + if str, ok := decoder.Decode(msg); ok { + decode = str + break + } + } + + traceMsg := &trace_pb.ChannelMessage{ + Timestamp: time.Now().UnixNano(), + Identity: handler.appId.Token, + Channel: ch.LogicalName(), + IsRx: rx, + ContentType: msg.ContentType, + Sequence: msg.Sequence(), + ReplyFor: msg.ReplyFor(), + Length: int32(len(msg.Body)), + Decode: decode, + } + + // This can result in a message send. Doing a send from inside a peekhandler can cause deadlocks, so it's best avoided + go handler.eventSink.Accept(traceMsg) +} + +func NewChannelSink(ch channel2.Channel) EventHandler { + return &channelSink{ch} +} + +type channelSink struct { + ch channel2.Channel +} + +func (sink *channelSink) Accept(event *trace_pb.ChannelMessage) { + log := pfxlog.Logger() + + bytes, err := proto.Marshal(event) + if err != nil { + log.Errorf("Failed to encode metrics message: %v", err) + return + } + + chMsg := channel2.NewMessage(int32(ctrl_pb.ContentType_TraceEventType), bytes) + + err = sink.ch.Send(chMsg) + if err != nil { + log.Errorf("Failed to send trace message: %v", err) + } else { + log.Tracef("Reported trace to fabric controller") + } +} \ No newline at end of file diff --git a/fabric/trace/controller.go b/fabric/trace/controller.go new file mode 100644 index 000000000..98b5cbe68 --- /dev/null +++ b/fabric/trace/controller.go @@ -0,0 +1,235 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package trace + +import ( + "github.com/netfoundry/ziti-foundation/trace/pb" + "fmt" + "regexp" + "strings" +) + +type controllerShutdown struct{} + +type SourceType int + +const ( + SourceTypePipe SourceType = iota +) + +type ToggleVerbosity int + +const ( + ToggleVerbosityNone ToggleVerbosity = iota + ToggleVerbosityMatches + ToggleVerbosityMisses + ToggleVerbosityAll +) + +func (val ToggleVerbosity) Show(matched bool) bool { + if matched { + return val == ToggleVerbosityMatches || val == ToggleVerbosityAll + } + return val == ToggleVerbosityMisses || val == ToggleVerbosityAll +} + +func GetVerbosity(verbosity trace_pb.TraceToggleVerbosity) ToggleVerbosity { + switch verbosity { + case trace_pb.TraceToggleVerbosity_ReportNone: + return ToggleVerbosityNone + case trace_pb.TraceToggleVerbosity_ReportMatches: + return ToggleVerbosityMatches + case trace_pb.TraceToggleVerbosity_ReportMisses: + return ToggleVerbosityMisses + case trace_pb.TraceToggleVerbosity_ReportAll: + return ToggleVerbosityAll + } + return ToggleVerbosityNone +} + +type SourceMatcher interface { + Matches(source string) bool +} + +type PipeToggleMatchers struct { + AppMatcher SourceMatcher + PipeMatcher SourceMatcher +} + +func NewPipeToggleMatchers(request *trace_pb.TogglePipeTracesRequest) (*PipeToggleMatchers, *ToggleResult) { + result := &ToggleResult{Success: true, Message: &strings.Builder{}} + + appRegex, err := regexp.Compile(request.AppRegex) + if err != nil { + result.Success = false + errMsg := fmt.Sprintf("Failed to parse app id regex '%v' with error: %v\n", request.AppRegex, err) + result.Message.WriteString(errMsg) + } + + pipeRegex, err := regexp.Compile(request.PipeRegex) + if err != nil { + result.Success = false + errMsg := fmt.Sprintf("Failed to parse pipe id regex '%v' with error: %v\n", request.PipeRegex, err) + result.Message.WriteString(errMsg) + } + + appMatcher := NewSourceMatcher(appRegex) + pipeMatcher := NewSourceMatcher(pipeRegex) + + return &PipeToggleMatchers{appMatcher, pipeMatcher}, result +} + +type ToggleResult struct { + Success bool + Message *strings.Builder +} + +func (result *ToggleResult) Append(msg string) { + result.Message.WriteString(msg) + result.Message.WriteString("\n") +} + +type ToggleApplyResult interface { + IsMatched() bool + GetMessage() string + Append(result *ToggleResult, verbosity ToggleVerbosity) +} + +type ToggleApplyResultImpl struct { + Matched bool + Message string +} + +func (applyResult *ToggleApplyResultImpl) IsMatched() bool { + return applyResult.Matched +} + +func (applyResult *ToggleApplyResultImpl) GetMessage() string { + return applyResult.Message +} + +func (applyResult *ToggleApplyResultImpl) Append(result *ToggleResult, verbosity ToggleVerbosity) { + if verbosity.Show(applyResult.Matched) { + result.Append(applyResult.Message) + } +} + +type sourceRegexpMatcher struct { + regex *regexp.Regexp +} + +func (matcher *sourceRegexpMatcher) Matches(source string) bool { + return matcher.regex.Match([]byte(source)) +} + +func NewSourceMatcher(regex *regexp.Regexp) SourceMatcher { + return &sourceRegexpMatcher{regex} +} + +type Source interface { + EnableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) + DisableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) +} + +type Controller interface { + EnableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) + DisableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) + AddSource(source Source) + RemoveSource(source Source) + Shutdown() +} + +func NewController() Controller { + controller := &controllerImpl{ + events: make(chan interface{}, 1), + sources: make(map[Source]Source), + } + go controller.run() + return controller +} + +type enableSourcesEvent struct { + sourceType SourceType + matcher SourceMatcher + resultChan chan<- ToggleApplyResult +} + +type disableSourcesEvent struct { + sourceType SourceType + matcher SourceMatcher + resultChan chan<- ToggleApplyResult +} + +type sourceAddedEvent struct { + source Source +} + +type sourceRemovedEvent struct { + source Source +} + +type controllerImpl struct { + events chan interface{} + sources map[Source]Source +} + +func (controller *controllerImpl) EnableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + controller.events <- &enableSourcesEvent{sourceType, matcher, resultChan} +} + +func (controller *controllerImpl) DisableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + controller.events <- &disableSourcesEvent{sourceType, matcher, resultChan} +} + +func (controller *controllerImpl) AddSource(source Source) { + controller.events <- &sourceAddedEvent{source} +} + +func (controller *controllerImpl) RemoveSource(source Source) { + controller.events <- &sourceRemovedEvent{source} +} + +func (controller *controllerImpl) Shutdown() { + controller.events <- &controllerShutdown{} +} + +func (controller *controllerImpl) run() { + running := true + for running { + select { + case i := <-controller.events: + switch event := i.(type) { + case *enableSourcesEvent: + for handler := range controller.sources { + handler.EnableTracing(event.sourceType, event.matcher, event.resultChan) + } + close(event.resultChan) + case *disableSourcesEvent: + for handler := range controller.sources { + handler.DisableTracing(event.sourceType, event.matcher, event.resultChan) + } + close(event.resultChan) + case *sourceAddedEvent: + controller.sources[event.source] = event.source + case *sourceRemovedEvent: + delete(controller.sources, event.source) + case *controllerShutdown: + running = false + } + } + } +} diff --git a/fabric/trace/event_controller.go b/fabric/trace/event_controller.go new file mode 100644 index 000000000..91d5af98a --- /dev/null +++ b/fabric/trace/event_controller.go @@ -0,0 +1,125 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package trace + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/trace/pb" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" +) + +// EventHandler is for types wishing to receive trace messages +type EventHandler interface { + Accept(event *trace_pb.ChannelMessage) +} + +// EventController allows for sending session changes to multiple Listeners +type EventController interface { + EventHandler + channel2.ReceiveHandler + + // AddHandler adds the given handler to the router + AddHandler(handler EventHandler) + + // RemoveHandler removes the given handler from the router + RemoveHandler(handler EventHandler) + + // Shutdown stops the router + Shutdown() +} + +// NewEventController creates a new EventController instance +func NewEventController() EventController { + router := &eventControllerImpl{ + changeChan: make(chan routerEvent, 1), + eventChan: make(chan *trace_pb.ChannelMessage, 25), + handlers: make(map[EventHandler]EventHandler), + } + + go router.run() + return router +} + +type eventControllerImpl struct { + changeChan chan routerEvent + eventChan chan *trace_pb.ChannelMessage + handlers map[EventHandler]EventHandler +} + +func (controller *eventControllerImpl) Accept(event *trace_pb.ChannelMessage) { + controller.eventChan <- event +} + +func (controller *eventControllerImpl) AddHandler(handler EventHandler) { + controller.changeChan <- routerEvent{handler, addHandlerChange} +} + +func (controller *eventControllerImpl) RemoveHandler(handler EventHandler) { + controller.changeChan <- routerEvent{handler, removeHandlerChange} +} + +func (controller *eventControllerImpl) Shutdown() { + controller.changeChan <- routerEvent{nil, shutdownEventControllerChange} +} + +func (controller *eventControllerImpl) run() { + running := true + for running { + select { + case change := <-controller.changeChan: + if addHandlerChange == change.changeType { + controller.handlers[change.handler] = change.handler + } else if removeHandlerChange == change.changeType { + delete(controller.handlers, change.handler) + } else if shutdownEventControllerChange == change.changeType { + running = false + } + case event := <-controller.eventChan: + for _, handler := range controller.handlers { + go handler.Accept(event) + } + } + } +} + +type eventControllerChangeType uint8 + +const ( + addHandlerChange = iota + removeHandlerChange + shutdownEventControllerChange +) + +type routerEvent struct { + handler EventHandler + changeType eventControllerChangeType +} + +func (*eventControllerImpl) ContentType() int32 { + return int32(ctrl_pb.ContentType_TraceEventType) +} + +func (controller *eventControllerImpl) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + event := &trace_pb.ChannelMessage{} + if err := proto.Unmarshal(msg.Body, event); err == nil { + controller.Accept(event) + } else { + pfxlog.Logger().Errorf("unexpected error decoding trace message (%s)", err) + } +} diff --git a/fabric/trace/filter.go b/fabric/trace/filter.go new file mode 100644 index 000000000..26da6199f --- /dev/null +++ b/fabric/trace/filter.go @@ -0,0 +1,67 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package trace + +import tracepb "github.com/netfoundry/ziti-foundation/trace/pb" + +type Filter interface { + Accept(event *tracepb.ChannelMessage) bool +} + +func NewAllowAllFilter() Filter { + return &allowAllFilter{} +} + +func NewIncludeFilter(includedContentTypes []int32) Filter { + return &includeFilter{contentTypes: includedContentTypes} +} + +func NewExcludeFilter(excludedContentTypes []int32) Filter { + return &excludeFilter{contentTypes: excludedContentTypes} +} + +type allowAllFilter struct{} + +func (*allowAllFilter) Accept(event *tracepb.ChannelMessage) bool { + return true +} + +type includeFilter struct { + contentTypes []int32 +} + +func (filter *includeFilter) Accept(event *tracepb.ChannelMessage) bool { + for _, contentType := range filter.contentTypes { + if event.ContentType == contentType { + return true + } + } + return false +} + +type excludeFilter struct { + contentTypes []int32 +} + +func (filter *excludeFilter) Accept(event *tracepb.ChannelMessage) bool { + for _, contentType := range filter.contentTypes { + if event.ContentType == contentType { + return false + } + } + return true +} diff --git a/fabric/trace/xgress_peekhandler.go b/fabric/trace/xgress_peekhandler.go new file mode 100644 index 000000000..1ccceea57 --- /dev/null +++ b/fabric/trace/xgress_peekhandler.go @@ -0,0 +1,110 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package trace + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + trace_pb "github.com/netfoundry/ziti-foundation/trace/pb" + "fmt" + "sync/atomic" + "time" +) + +type XgressPeekHandler struct { + appId *identity.TokenId + enabled int32 + controller Controller + decoders []channel2.TraceMessageDecoder + eventSink EventHandler +} + +func (handler *XgressPeekHandler) EnableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + handler.ToggleTracing(sourceType, matcher, true, resultChan) +} + +func (handler *XgressPeekHandler) DisableTracing(sourceType SourceType, matcher SourceMatcher, resultChan chan<- ToggleApplyResult) { + handler.ToggleTracing(sourceType, matcher, false, resultChan) +} + +func (handler *XgressPeekHandler) ToggleTracing(sourceType SourceType, matcher SourceMatcher, enable bool, resultChan chan<- ToggleApplyResult) { + name := "xgress" + matched := sourceType == SourceTypePipe && matcher.Matches(name) + prevState := handler.IsEnabled() + nextState := prevState + if matched { + handler.enable(enable) + nextState = enable + } + resultChan <- &ToggleApplyResultImpl{matched, + fmt.Sprintf("Link %v.%v matched? %v. Old trace state: %v, New trace state: %v", + handler.appId.Token, name, matched, prevState, nextState)} +} + +func (handler *XgressPeekHandler) Rx(x *xgress.Xgress, payload *xgress.Payload) { + handler.trace(x, payload, true) +} + +func (handler *XgressPeekHandler) Tx(x *xgress.Xgress, payload *xgress.Payload) { + handler.trace(x, payload, false) +} + +func (handler *XgressPeekHandler) Close(x *xgress.Xgress) { + panic("implement me") +} + +func NewXgressPeekHandler(appId *identity.TokenId, controller Controller, eventSink EventHandler) *XgressPeekHandler { + + handler := &XgressPeekHandler{ + appId: appId, + enabled: 0, + controller: controller, + decoders: decoders, + eventSink: eventSink, + } + controller.AddSource(handler) + return handler +} + +func (handler *XgressPeekHandler) enable(enabled bool) { + atomic.StoreInt32(&handler.enabled, btoi(enabled)) +} + +func (handler *XgressPeekHandler) IsEnabled() bool { + return atomic.LoadInt32(&handler.enabled) == 1 +} + +func (handler *XgressPeekHandler) trace(x *xgress.Xgress, payload *xgress.Payload, rx bool) { + + decode, _ := xgress.DecodePayload(payload) + + traceMsg := &trace_pb.ChannelMessage{ + Timestamp: time.Now().UnixNano(), + Identity: handler.appId.Token, + Channel: x.Label(), + IsRx: rx, + ContentType: xgress.ContentTypePayloadType, + Sequence: -1, + ReplyFor: -1, + Length: int32(len(payload.Data)), + Decode: decode, + } + + // This can result in a message send. Doing a send from inside a peekhandler can cause deadlocks, so it's best avoided + handler.eventSink.Accept(traceMsg) +} diff --git a/fabric/xctrl/ops.go b/fabric/xctrl/ops.go new file mode 100644 index 000000000..6e65a740d --- /dev/null +++ b/fabric/xctrl/ops.go @@ -0,0 +1,59 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "time" +) + +type Capabilities struct { + channel2.Channel +} + +func (capabilities *Capabilities) Get(timeout time.Duration) ([]string, error) { + request := &ctrl_pb.InspectRequest{RequestedValues: []string{"capability"}} + response := &ctrl_pb.InspectResponse{} + if err := capabilities.Channel.SendForReplyAndDecode(request, timeout, response); err != nil { + return nil, err + } + var result []string + for _, value := range response.Values { + if value.Name == "capability" { + result = append(result, value.Value) + } + } + return result, nil +} + +func (capabilities *Capabilities) Has(capability string, timeout time.Duration) (bool, error) { + capabilityList, err := capabilities.Get(timeout) + if err != nil { + return false, err + } + for _, cap := range capabilityList { + if cap == capability { + return true, nil + } + } + return false, nil +} + +func (capabilities *Capabilities) IsEdgeCapable(timeout time.Duration) (bool, error) { + return capabilities.Has("ziti.edge", timeout) +} diff --git a/fabric/xctrl/xctrl.go b/fabric/xctrl/xctrl.go new file mode 100644 index 000000000..0f7c54d86 --- /dev/null +++ b/fabric/xctrl/xctrl.go @@ -0,0 +1,30 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xctrl + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/config" + "github.com/netfoundry/ziti-foundation/storage/boltz" +) + +type Xctrl interface { + config.Subconfig + channel2.BindHandler + Enabled() bool + Run(ctrl channel2.Channel, db boltz.Db, done chan struct{}) error +} diff --git a/fabric/xctrl_example/example.go b/fabric/xctrl_example/example.go new file mode 100644 index 000000000..c72eabdfa --- /dev/null +++ b/fabric/xctrl_example/example.go @@ -0,0 +1,90 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xctrl_example + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/xctrl" + "github.com/netfoundry/ziti-foundation/storage/boltz" + "bytes" + "encoding/binary" + "errors" + "github.com/michaelquigley/pfxlog" + "time" +) + +type example struct { + count int32 + delay int + enabled bool +} + +func NewExample() xctrl.Xctrl { + return &example{delay: 1, enabled: false} +} + +func (example *example) LoadConfig(cfgmap map[interface{}]interface{}) error { + if value, found := cfgmap["example"]; found { + if submap, ok := value.(map[interface{}]interface{}); ok { + if value, found := submap["delay"]; found { + delay, ok := value.(int) + if !ok { + return errors.New("expected int value for [example/delay]") + } + example.delay = delay + } + } + example.enabled = true + } + return nil +} + +func (example *example) Enabled() bool { + return example.enabled +} + +func (example *example) BindChannel(ch channel2.Channel) error { + ch.AddReceiveHandler(newReceiveHandler()) + return nil +} + +func (example *example) Run(ctrl channel2.Channel, _ boltz.Db, done chan struct{}) error { + go func() { + for { + select { + case <-done: + pfxlog.Logger().Infof("exiting") + return + + case <-time.After(time.Duration(example.delay) * time.Second): + body := new(bytes.Buffer) + if err := binary.Write(body, binary.LittleEndian, example.count); err != nil { + pfxlog.Logger().Errorf("unexpected error marshaling (%s)", err) + } + msg := channel2.NewMessage(contentType, body.Bytes()) + if err := ctrl.Send(msg); err != nil { + pfxlog.Logger().Errorf("unexpected error sending (%s)", err) + } + pfxlog.Logger().Infof("sent [%d]", example.count) + example.count++ + } + } + }() + return nil +} + +const contentType = 99999 diff --git a/fabric/xctrl_example/receive.go b/fabric/xctrl_example/receive.go new file mode 100644 index 000000000..f11b1a1da --- /dev/null +++ b/fabric/xctrl_example/receive.go @@ -0,0 +1,48 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xctrl_example + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "bytes" + "encoding/binary" + "github.com/michaelquigley/pfxlog" +) + +type receiveHandler struct{} + +func newReceiveHandler() channel2.ReceiveHandler { + return &receiveHandler{} +} + +func (h *receiveHandler) ContentType() int32 { + return contentType +} + +func (h *receiveHandler) HandleReceive(msg *channel2.Message, ch channel2.Channel) { + if len(msg.Body) == 4 { + buf := bytes.NewBuffer(msg.Body) + var count int32 + if err := binary.Read(buf, binary.LittleEndian, &count); err == nil { + pfxlog.Logger().Infof("received [%d]", count) + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + } + } else { + pfxlog.Logger().Errorf("unexpected body length [%d]", len(msg.Body)) + } +} \ No newline at end of file diff --git a/fabric/xgress/ctrl.go b/fabric/xgress/ctrl.go new file mode 100644 index 000000000..c64a45f16 --- /dev/null +++ b/fabric/xgress/ctrl.go @@ -0,0 +1,25 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/channel2" +) + +type CtrlChannel interface { + Channel() channel2.Channel +} diff --git a/fabric/xgress/decoder.go b/fabric/xgress/decoder.go new file mode 100644 index 000000000..2bcdd1a1a --- /dev/null +++ b/fabric/xgress/decoder.go @@ -0,0 +1,86 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "fmt" + "github.com/michaelquigley/pfxlog" +) + +type Decoder struct{} + +const DECODER = "data" + +func (d Decoder) Decode(msg *channel2.Message) ([]byte, bool) { + switch msg.ContentType { + case int32(ContentTypePayloadType): + if payload, err := UnmarshallPayload(msg); err == nil { + return DecodePayload(payload) + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + } + + case int32(ContentTypeAcknowledgementType): + if ack, err := UnmarshallAcknowledgement(msg); err == nil { + meta := channel2.NewTraceMessageDecode(DECODER, "Acknowledgement") + meta["sessionId"] = ack.SessionId + meta["sequence"] = fmt.Sprintf("len(%d)", len(ack.Sequence)) + switch ack.GetOriginator() { + case Initiator: + meta["originator"] = "i" + case Terminator: + meta["originator"] = "e" + } + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true + + } else { + pfxlog.Logger().Errorf("unexpected error (%s)", err) + } + } + + return nil, false +} + +func DecodePayload(payload *Payload) ([]byte, bool) { + meta := channel2.NewTraceMessageDecode(DECODER, "Payload") + meta["sessionId"] = payload.SessionId + meta["sequence"] = payload.Sequence + switch payload.GetOriginator() { + case Initiator: + meta["originator"] = "i" + case Terminator: + meta["originator"] = "e" + } + if payload.flags != 0 { + meta["flags"] = payload.flags + } + meta["length"] = len(payload.Data) + + data, err := meta.MarshalTraceMessageDecode() + if err != nil { + return nil, true + } + + return data, true +} diff --git a/fabric/xgress/messages.go b/fabric/xgress/messages.go new file mode 100644 index 000000000..c996189a9 --- /dev/null +++ b/fabric/xgress/messages.go @@ -0,0 +1,249 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/util/uuidz" + "encoding/binary" + "fmt" + "github.com/sirupsen/logrus" + "math" +) + +const ( + MinHeaderKey = 2000 + MaxHeaderKey = MinHeaderKey + int32(math.MaxUint8) + + HeaderKeySessionId = 2256 + HeaderKeySequence = 2257 + HeaderKeyFlags = 2258 + + ContentTypePayloadType = 1100 + ContentTypeAcknowledgementType = 1101 +) + +var ContentTypeValue = map[string]int32{ + "PayloadType": ContentTypePayloadType, + "AcknowledgementType": ContentTypeAcknowledgementType, +} + +type Originator int32 + +const ( + Initiator Originator = 0 + Terminator Originator = 1 +) + +func (o Originator) String() string { + if o == Initiator { + return "Initiator" + } + return "Terminator" +} + +type PayloadFlag uint32 + +const ( + PayloadFlagSessionEnd PayloadFlag = 1 + PayloadFlagEgress PayloadFlag = 2 +) + +type Header struct { + SessionId string + flags uint32 +} + +func (header *Header) GetSessionId() string { + return header.SessionId +} + +func (header *Header) GetFlags() string { + return header.SessionId +} + +func (header *Header) GetOriginator() Originator { + if isPayloadFlagSet(header.flags, PayloadFlagEgress) { + return Terminator + } + return Initiator +} + +func (header *Header) unmarshallHeader(msg *channel2.Message) error { + sessionId, ok := msg.Headers[HeaderKeySessionId] + if !ok { + return fmt.Errorf("no sessionId found in xgress payload message") + } + + // If no flags are present, it just means no flags have been set + flags, _ := msg.GetUint32Header(HeaderKeyFlags) + + header.SessionId = string(sessionId) + header.flags = flags + + return nil +} + +func (header *Header) marshallHeader(msg *channel2.Message) { + msg.Headers[HeaderKeySessionId] = []byte(header.SessionId) + if header.flags != 0 { + msg.PutUint32Header(HeaderKeyFlags, header.flags) + } +} + +func NewAcknowledgement(sessionId string, originator Originator) *Acknowledgement { + return &Acknowledgement{ + Header: Header{ + SessionId: sessionId, + flags: SetOriginatorFlag(0, originator), + }, + } +} + +type Acknowledgement struct { + Header + Sequence []int32 +} + +func (ack *Acknowledgement) GetSequence() []int32 { + return ack.Sequence +} + +func (ack *Acknowledgement) marshallSequence() []byte { + if len(ack.Sequence) == 0 { + return nil + } + buf := make([]byte, len(ack.Sequence)*4) + nextWriteBuf := buf + for _, seq := range ack.Sequence { + binary.BigEndian.PutUint32(nextWriteBuf, uint32(seq)) + nextWriteBuf = nextWriteBuf[4:] + } + return buf +} + +func (ack *Acknowledgement) unmarshallSequence(data []byte) error { + if len(data) == 0 { + return nil + } + + if len(data)%4 != 0 { + return fmt.Errorf("received sequence with wrong number of bytes: %v", len(data)) + } + ack.Sequence = make([]int32, len(data)/4) + + nextReadBuf := data + for i, _ := range ack.Sequence { + ack.Sequence[i] = int32(binary.BigEndian.Uint32(nextReadBuf)) + nextReadBuf = nextReadBuf[4:] + } + return nil +} + +func (ack *Acknowledgement) Marshall() *channel2.Message { + msg := channel2.NewMessage(ContentTypeAcknowledgementType, ack.marshallSequence()) + ack.marshallHeader(msg) + return msg +} + +func UnmarshallAcknowledgement(msg *channel2.Message) (*Acknowledgement, error) { + ack := &Acknowledgement{} + + if err := ack.unmarshallHeader(msg); err != nil { + return nil, err + } + if err := ack.unmarshallSequence(msg.Body); err != nil { + return nil, err + } + + return ack, nil +} + +type Payload struct { + Header + Sequence int32 + Headers map[uint8][]byte + Data []byte +} + +func (payload *Payload) GetSequence() int32 { + return payload.Sequence +} + +func (payload *Payload) Marshall() *channel2.Message { + msg := channel2.NewMessage(ContentTypePayloadType, payload.Data) + for key, value := range payload.Headers { + msgHeaderKey := MinHeaderKey + int32(key) + msg.Headers[msgHeaderKey] = value + } + payload.marshallHeader(msg) + msg.PutUint64Header(HeaderKeySequence, uint64(payload.Sequence)) + return msg +} + +func UnmarshallPayload(msg *channel2.Message) (*Payload, error) { + var headers map[uint8][]byte + for key, val := range msg.Headers { + if key >= MinHeaderKey && key <= MaxHeaderKey { + if headers == nil { + headers = make(map[uint8][]byte) + } + xgressHeaderKey := uint8(key - MinHeaderKey) + headers[xgressHeaderKey] = val + } + } + + payload := &Payload{ + Headers: headers, + Data: msg.Body, + } + + if err := payload.unmarshallHeader(msg); err != nil { + return nil, err + } + + sequence, ok := msg.GetUint64Header(HeaderKeySequence) + if !ok { + return nil, fmt.Errorf("no sequence found in xgress payload message") + } + payload.Sequence = int32(sequence) + + return payload, nil +} + +func isPayloadFlagSet(flags uint32, flag PayloadFlag) bool { + return PayloadFlag(flags)&flag == flag +} + +func (payload *Payload) IsSessionEndFlagSet() bool { + return isPayloadFlagSet(payload.flags, PayloadFlagSessionEnd) +} + +func SetOriginatorFlag(flags uint32, originator Originator) uint32 { + if originator == Initiator { + return ^uint32(PayloadFlagEgress) & flags + } + return uint32(PayloadFlagEgress) | flags +} + +func (payload *Payload) GetLoggerFields() logrus.Fields { + return logrus.Fields{ + "seq": payload.Sequence, + "origin": payload.GetOriginator(), + "uuid": uuidz.ToString(payload.Headers[HeaderKeyUUID]), + } +} \ No newline at end of file diff --git a/fabric/xgress/messages_test.go b/fabric/xgress/messages_test.go new file mode 100644 index 000000000..129c40fc7 --- /dev/null +++ b/fabric/xgress/messages_test.go @@ -0,0 +1,108 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/stretchr/testify/assert" + "reflect" + "testing" +) + +func TestSetOriginatorFlag(t *testing.T) { + type args struct { + flags uint32 + originator Originator + } + tests := []struct { + name string + args args + want uint32 + }{ + struct { + name string + args args + want uint32 + }{name: "set empty to ingress", + args: args{ + flags: 0, + originator: Initiator, + }, + want: 0, + }, + {name: "set end of session to ingress", + args: args{ + flags: uint32(PayloadFlagSessionEnd), + originator: Initiator, + }, + want: uint32(PayloadFlagSessionEnd), + }, + {name: "set empty to egress", + args: args{ + flags: 0, + originator: Terminator, + }, + want: uint32(PayloadFlagEgress), + }, + {name: "set end of session to egress", + args: args{ + flags: uint32(PayloadFlagSessionEnd), + originator: Terminator, + }, + want: uint32(PayloadFlagSessionEnd) | uint32(PayloadFlagEgress), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SetOriginatorFlag(tt.args.flags, tt.args.originator); got != tt.want { + t.Errorf("SetOriginatorFlag() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAcknowledgement_marshallSequence(t *testing.T) { + tests := []struct { + name string + sequence []int32 + }{ + struct { + name string + sequence []int32 + }{name: "nil", sequence: nil}, + {name: "empty", sequence: make([]int32, 0)}, + {name: "one entry", sequence: []int32{1}}, + {name: "many entries", sequence: []int32{1, -1, 100, 200, -3213232, 421123, -58903204, -4324, 432432, 0, 9}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ack := &Acknowledgement{ + Sequence: tt.sequence, + } + got := ack.marshallSequence(); + ack2 := &Acknowledgement{} + err := ack2.unmarshallSequence(got) + assert.NoError(t, err) + + if len(ack.Sequence) == 0 && len(ack.Sequence) == 0 { + return + } + if !reflect.DeepEqual(ack, ack2) { + t.Errorf("marshallSequence() = %v, want %v", ack2, ack) + } + }) + } +} \ No newline at end of file diff --git a/fabric/xgress/options.go b/fabric/xgress/options.go new file mode 100644 index 000000000..3ae7c6c1b --- /dev/null +++ b/fabric/xgress/options.go @@ -0,0 +1,64 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "encoding/json" +) + +// Options contains common Xgress configuration options +type Options struct { + Retransmission bool + RandomDrops bool + Drop1InN int32 +} + +func LoadOptions(data XgressOptionsData) *Options { + options := DefaultOptions() + + if value, found := data["options"]; found { + data = value.(map[interface{}]interface{}) + + if value, found := data["retransmission"]; found { + options.Retransmission = value.(bool) + } + if value, found := data["randomDrops"]; found { + options.RandomDrops = value.(bool) + } + if value, found := data["drop1InN"]; found { + options.Drop1InN = int32(value.(int)) + } + } + + return options +} + +func DefaultOptions() *Options { + return &Options{ + Retransmission: true, + RandomDrops: false, + Drop1InN: 100, + } +} + +func (options Options) String() string { + data, err := json.Marshal(options) + if err != nil { + return err.Error() + } + return string(data) +} \ No newline at end of file diff --git a/fabric/xgress/payload_buffer.go b/fabric/xgress/payload_buffer.go new file mode 100644 index 000000000..9d8b6a9fa --- /dev/null +++ b/fabric/xgress/payload_buffer.go @@ -0,0 +1,310 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/info" + "errors" + "fmt" + "github.com/michaelquigley/pfxlog" + "github.com/orcaman/concurrent-map" + "time" +) + +type PayloadBufferForwarder interface { + ForwardPayload(srcAddr Address, payload *Payload) error + ForwardAcknowledgement(srcAddr Address, acknowledgement *Acknowledgement) error +} + +type PayloadBufferController struct { + buffers cmap.ConcurrentMap // map[sessionId.Token]*PayloadBuffer + forwarder PayloadBufferForwarder +} + +func NewPayloadBufferController(forwarder PayloadBufferForwarder) *PayloadBufferController { + return &PayloadBufferController{ + buffers: cmap.New(), + forwarder: forwarder, + } +} + +func (controller *PayloadBufferController) BufferForSession(sessionId *identity.TokenId, address Address) *PayloadBuffer { + bufferId := string(address) + sessionId.Token + if i, found := controller.buffers.Get(bufferId); found { + return i.(*PayloadBuffer) + } + + buffer := NewPayloadBuffer(sessionId, controller.forwarder) + controller.buffers.Set(bufferId, buffer) + return buffer +} + +func (controller *PayloadBufferController) EndSession(sessionId *identity.TokenId) { + if i, found := controller.buffers.Get(sessionId.Token); found { + i.(*PayloadBuffer).Close() + controller.buffers.Remove(sessionId.Token) + } +} + +type PayloadBuffer struct { + sessionId *identity.TokenId + buffer map[int32]*payloadAge + newlyBuffered chan *Payload + acked map[int32]int64 + lastAck int64 + newlyAcknowledged chan *Payload + newlyReceivedAcks chan *Acknowledgement + receivedAckHwm int32 + forwarder PayloadBufferForwarder + SrcAddress Address + Originator Originator + + config struct { + retransmitAge int64 + ackPeriod int64 + ackCount int + idleAckAfter int64 + } +} + +type payloadAge struct { + payload *Payload + age int64 +} + +func NewPayloadBuffer(sessionId *identity.TokenId, forwarder PayloadBufferForwarder) *PayloadBuffer { + buffer := &PayloadBuffer{ + sessionId: sessionId, + buffer: make(map[int32]*payloadAge), + newlyBuffered: make(chan *Payload), + acked: make(map[int32]int64), + lastAck: info.NowInMilliseconds(), + newlyAcknowledged: make(chan *Payload), + newlyReceivedAcks: make(chan *Acknowledgement), + receivedAckHwm: -1, + forwarder: forwarder, + } + + buffer.config.retransmitAge = 2000 + buffer.config.ackPeriod = 1000 + buffer.config.ackCount = 96 + buffer.config.idleAckAfter = 5000 + + go buffer.run() + return buffer +} + +func (buffer *PayloadBuffer) BufferPayload(payload *Payload) { + defer func() { + if r := recover(); r != nil { + pfxlog.ContextLogger("s/" + buffer.sessionId.Token).Error("send on closed channel") + } + }() + buffer.newlyBuffered <- payload + pfxlog.ContextLogger("s/"+payload.GetSessionId()).Debugf("buffered [%d]", payload.GetSequence()) +} + +func (buffer *PayloadBuffer) AcknowledgePayload(payload *Payload) { + defer func() { + if r := recover(); r != nil { + pfxlog.ContextLogger("s/" + buffer.sessionId.Token).Error("send on closed channel") + } + }() + buffer.newlyAcknowledged <- payload + pfxlog.ContextLogger("s/"+payload.GetSessionId()).Debugf("acknowledge [%d]", payload.GetSequence()) +} + +func (buffer *PayloadBuffer) ReceiveAcknowledgement(ack *Acknowledgement) { + defer func() { + if r := recover(); r != nil { + pfxlog.ContextLogger("s/" + buffer.sessionId.Token).Error("send on closed channel") + } + }() + buffer.newlyReceivedAcks <- ack + pfxlog.ContextLogger("s/"+ack.SessionId).Debugf("received ack [%d]", len(ack.Sequence)) +} + +func (buffer *PayloadBuffer) Close() { + defer func() { + if r := recover(); r != nil { + pfxlog.Logger().Debug("already closed") + } + }() + close(buffer.newlyBuffered) + close(buffer.newlyAcknowledged) + close(buffer.newlyReceivedAcks) +} + +func (buffer *PayloadBuffer) run() { + log := pfxlog.ContextLogger("s/" + buffer.sessionId.Token) + defer log.Debug("exited") + log.Debug("started") + + lastDebug := info.NowInMilliseconds() + for { + now := info.NowInMilliseconds() + if now-lastDebug >= 2000 { + buffer.debug(now) + lastDebug = now + } + + select { + case ack := <-buffer.newlyReceivedAcks: + if ack != nil { + if err := buffer.receiveAcknowledgement(ack); err != nil { + log.Errorf("unexpected error (%s)", err) + } + } else { + return + } + if err := buffer.retransmit(); err != nil { + log.Errorf("unexpected error retransmitting (%s)", err) + } + + case payload := <-buffer.newlyAcknowledged: + if payload != nil { + if err := buffer.acknowledgePayload(payload); err != nil { + log.Errorf("unexpected error (%s)", err) + } + if err := buffer.acknowledge(); err != nil { + log.Errorf("unexpected error (%s)", err) + } + } else { + return + } + + case payload := <-buffer.newlyBuffered: + if payload != nil { + if err := buffer.bufferPayload(payload); err != nil { + log.Errorf("unexpected error (%s)", err) + } + if err := buffer.acknowledge(); err != nil { + log.Errorf("unexpected error (%s)", err) + } + } else { + return + } + + case <-time.After(time.Duration(buffer.config.idleAckAfter) * time.Millisecond): + if err := buffer.acknowledge(); err != nil { + log.Errorf("unexpected error acknowledging (%s)", err) + } + if err := buffer.retransmit(); err != nil { + log.Errorf("unexpected error retransmitting (%s)", err) + } + } + } +} + +func (buffer *PayloadBuffer) bufferPayload(payload *Payload) error { + if buffer.sessionId.Token == payload.GetSessionId() { + buffer.buffer[payload.GetSequence()] = &payloadAge{payload: payload, age: info.NowInMilliseconds()} + + } else { + return errors.New("unexpected Payload") + } + + return nil +} + +func (buffer *PayloadBuffer) acknowledgePayload(payload *Payload) error { + if buffer.sessionId.Token == payload.SessionId { + buffer.acked[payload.Sequence] = info.NowInMilliseconds() + + } else { + return errors.New("unexpected Payload") + } + + return nil +} + +func (buffer *PayloadBuffer) receiveAcknowledgement(ack *Acknowledgement) error { + log := pfxlog.ContextLogger("s/" + buffer.sessionId.Token) + if buffer.sessionId.Token == ack.SessionId { + for _, sequence := range ack.Sequence { + if sequence > buffer.receivedAckHwm { + buffer.receivedAckHwm = sequence + } + delete(buffer.buffer, sequence) + log.Debugf("acknowledged sequence [%d]", sequence) + } + + } else { + return errors.New("unexpected acknowledgement") + } + return nil +} + +func (buffer *PayloadBuffer) acknowledge() error { + log := pfxlog.ContextLogger("s/" + buffer.sessionId.Token) + now := info.NowInMilliseconds() + + if now-buffer.lastAck >= buffer.config.ackPeriod || len(buffer.acked) >= buffer.config.ackCount { + log.Debug("ready to acknowledge") + + ack := NewAcknowledgement(buffer.sessionId.Token, buffer.Originator) + for sequence := range buffer.acked { + ack.Sequence = append(ack.Sequence, sequence) + } + log.Debugf("acknowledging [%d] payloads, [%d] buffered", len(ack.Sequence), len(buffer.buffer)) + + if err := buffer.forwarder.ForwardAcknowledgement(buffer.SrcAddress, ack); err != nil { + return err + } + + buffer.acked = make(map[int32]int64) // clear + buffer.lastAck = now + + } else { + log.Debug("not ready to acknowledge") + } + + return nil +} + +func (buffer *PayloadBuffer) retransmit() error { + if len(buffer.buffer) > 0 { + log := pfxlog.ContextLogger(fmt.Sprintf("s/" + buffer.sessionId.Token)) + + now := info.NowInMilliseconds() + var unacked []*Payload + for _, v := range buffer.buffer { + if v.payload.GetSequence() < buffer.receivedAckHwm && now-v.age > buffer.config.retransmitAge { + unacked = append(unacked, v.payload) + v.age = now + } + } + if len(unacked) > 0 { + for _, payload := range unacked { + if err := buffer.forwarder.ForwardPayload(buffer.SrcAddress, payload); err != nil { + return err + } + } + log.Infof("retransmitted [%d] payloads, [%d] buffered", len(unacked), len(buffer.buffer)) + + } else { + log.Debug("no payloads to retransmit") + } + } + return nil +} + +func (buffer *PayloadBuffer) debug(now int64) { + pfxlog.ContextLogger(buffer.sessionId.Token).Debugf("buffer=[%d], acked=[%d], lastAck=[%d ms.], receivedAckHwm=[%d]", + len(buffer.buffer), len(buffer.acked), now-buffer.lastAck, buffer.receivedAckHwm) +} diff --git a/fabric/xgress/registry.go b/fabric/xgress/registry.go new file mode 100644 index 000000000..9d1463c92 --- /dev/null +++ b/fabric/xgress/registry.go @@ -0,0 +1,69 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "fmt" +) + +type registry struct { + factories map[string]XgressFactory +} + +func NewXgressRegistry() *registry { + return ®istry{ + factories: make(map[string]XgressFactory), + } +} + +func (registry *registry) Register(name string, factory XgressFactory) { + registry.factories[name] = factory +} + +func (registry *registry) Factory(name string) (XgressFactory, error) { + if factory, found := registry.factories[name]; found { + return factory, nil + } else { + return nil, fmt.Errorf("xgress factory [%s] not found", name) + } +} + +func (registry *registry) List() []string { + names := make([]string, 0) + for k := range registry.factories { + names = append(names, k) + } + return names +} + +func (registry *registry) Debug() string { + out := "{" + for _, name := range registry.List() { + out += " " + name + } + out += " }" + return out +} + +var globalRegistry *registry + +func GlobalRegistry() *registry { + if globalRegistry == nil { + globalRegistry = NewXgressRegistry() + } + return globalRegistry +} diff --git a/fabric/xgress/request.go b/fabric/xgress/request.go new file mode 100644 index 000000000..651f1b4e3 --- /dev/null +++ b/fabric/xgress/request.go @@ -0,0 +1,288 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-fabric/fabric/ctrl_msg" + "github.com/netfoundry/ziti-fabric/fabric/pb/ctrl_pb" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "encoding/json" + "github.com/golang/protobuf/proto" + "github.com/michaelquigley/pfxlog" + "github.com/pkg/errors" + "io" + "time" +) + +type Request struct { + Id string `json:"id"` + ServiceId string `json:"svcId"` +} + +func RequestFromJSON(payload []byte) (*Request, error) { + request := &Request{} + err := json.Unmarshal(payload, request) + if err != nil { + return nil, err + } + return request, nil +} + +func (r *Request) ToJSON() ([]byte, error) { + bytes, err := json.Marshal(r) + if err != nil { + return nil, err + } + return bytes, nil +} + +type Response struct { + Success bool `json:"scc"` + Message string `json:"msg"` +} + +func ResponseFromJSON(payload []byte) (*Response, error) { + response := &Response{} + err := json.Unmarshal(payload, response) + if err != nil { + return nil, err + } + return response, nil +} + +func (r *Response) ToJSON() ([]byte, error) { + bytes, err := json.Marshal(r) + if err != nil { + return nil, err + } + return bytes, nil +} + +func SendRequest(request *Request, peer io.Writer) error { + requestJSON, err := request.ToJSON() + if err != nil { + return err + } + _, err = peer.Write(append(requestJSON, []byte{'\n'}...)) + if err != nil { + return err + } + return nil +} + +func ReceiveRequest(peer transport.Connection) (*Request, error) { + line, err := transport.ReadUntilNewline(peer) + if err != nil { + return nil, err + } + + request, err := RequestFromJSON(line) + if err != nil { + return nil, err + } + + return request, nil +} + +func SendResponse(response *Response, peer io.Writer) error { + responseJSON, err := response.ToJSON() + if err != nil { + return err + } + _, err = peer.Write(append(responseJSON, []byte{'\n'}...)) + if err != nil { + return err + } + return nil +} + +func ReceiveResponse(peer transport.Connection) (*Response, error) { + line, err := transport.ReadUntilNewline(peer) + if err != nil { + return nil, err + } + + response, err := ResponseFromJSON(line) + if err != nil { + return nil, err + } + + return response, nil +} + +type SessionInfo struct { + SessionId *identity.TokenId + Address Address + ResponseMsg *channel2.Message + ctrl CtrlChannel +} + +func (si *SessionInfo) SendStartEgress() error { + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_StartXgressType), nil) + msg.ReplyTo(si.ResponseMsg) + return si.ctrl.Channel().SendWithTimeout(msg, time.Second*5) +} + +var authError = errors.New("unexpected failure while authenticating") + +func GetSession(ctrl CtrlChannel, ingressId string, serviceId string) (*SessionInfo, error) { + log := pfxlog.Logger() + sessionRequest := &ctrl_pb.SessionRequest{ + IngressId: ingressId, + ServiceId: serviceId, + } + bytes, err := proto.Marshal(sessionRequest) + if err != nil { + log.Errorf("failed to marshal SessionRequest message: (%v)", err) + return nil, authError + } + + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_SessionRequestType), bytes) + reply, err := ctrl.Channel().SendAndWaitWithTimeout(msg, time.Second*5) + if err != nil { + log.Errorf("failed to send SessionRequest message: (%v)", err) + return nil, authError + } + + if reply.ContentType == ctrl_msg.ContentTypeSessionSuccessType { + sessionId := &identity.TokenId{Token: string(reply.Body)} + address := string(reply.Headers[ctrl_msg.SessionSuccessAddressHeader]) + log.Debugf("created new session [s/%s]", sessionId.Token) + return &SessionInfo{ + SessionId: sessionId, + Address: Address(address), + ResponseMsg: reply, + ctrl: ctrl}, nil + } else if reply.ContentType == ctrl_msg.ContentTypeSessionFailedType { + errMsg := string(reply.Body) + log.Errorf("authentication failure: (%v)", errMsg) + return nil, errors.New(errMsg) + } else { + log.Errorf("unexpected controller response, ContentType: (%v)", msg.ContentType) + return nil, authError + } + +} + +func CreateSession(ctrl CtrlChannel, peer Connection, request *Request, bindHandler BindHandler, options *Options) *Response { + sessionInfo, err := GetSession(ctrl, request.Id, request.ServiceId) + if err != nil { + return &Response{Success: false, Message: err.Error()} + } + + x := NewXgress(sessionInfo.SessionId, sessionInfo.Address, peer, Initiator, options) + bindHandler.HandleXgressBind(sessionInfo.SessionId, sessionInfo.Address, Initiator, x) + x.Start() + + if err = sessionInfo.SendStartEgress(); err != nil { + return &Response{Success: false, Message: err.Error()} + } + return &Response{Success: true} +} + +func BindService(ctrl CtrlChannel, token string, serviceId string) error { + log := pfxlog.Logger() + hostRequest := &ctrl_pb.BindRequest{ + BindType: ctrl_pb.BindType_Bind, + Token: token, + ServiceId: serviceId, + } + bytes, err := proto.Marshal(hostRequest) + if err != nil { + log.Errorf("failed to marshal BindRequest message: (%v)", err) + return authError + } + + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_BindRequestType), bytes) + waitCh, err := ctrl.Channel().SendAndWait(msg) + if err != nil { + log.Errorf("failed to send BindRequest message: (%v)", err) + return authError + } + + select { + case msg := <-waitCh: + if msg != nil && msg.ContentType == int32(ctrl_pb.ContentType_BindResponseType) { + bindResponse := &ctrl_pb.BindResponse{} + err := proto.Unmarshal(msg.Body, bindResponse) + if err != nil { + log.Errorf("failed to send un-marshall BindResponse message: (%v)", err) + return authError + } + if bindResponse.Success { + log.Debugf("successfully bound session [s/%s]", token) + return nil + } + log.Errorf("authentication failure: (%v)", bindResponse.Message) + return errors.New(bindResponse.Message) + } else { + log.Errorf("unexpected controller response, ContentType: (%v)", msg.ContentType) + return authError + } + + case <-time.After(5 * time.Second): + return errors.New("timeout while binding") + } +} + +func UnbindService(ctrl CtrlChannel, token string, serviceId string) error { + log := pfxlog.Logger() + hostRequest := &ctrl_pb.BindRequest{ + BindType: ctrl_pb.BindType_Unbind, + Token: token, + ServiceId: serviceId, + } + bytes, err := proto.Marshal(hostRequest) + if err != nil { + log.Errorf("failed to marshal BindRequest message: (%v)", err) + return authError + } + + msg := channel2.NewMessage(int32(ctrl_pb.ContentType_BindRequestType), bytes) + waitCh, err := ctrl.Channel().SendAndWait(msg) + if err != nil { + log.Errorf("failed to send HostRequest message: (%v)", err) + return authError + } + + select { + case msg := <-waitCh: + if msg != nil && msg.ContentType == int32(ctrl_pb.ContentType_BindResponseType) { + bindResponse := &ctrl_pb.BindResponse{} + err := proto.Unmarshal(msg.Body, bindResponse) + if err != nil { + log.Errorf("failed to send un-marshall BindResponse message: (%v)", err) + return authError + } + if bindResponse.Success { + log.Debugf("successfully unbound session [s/%s]", token) + return nil + } + log.Errorf("authentication failure: (%v)", bindResponse.Message) + return errors.New(bindResponse.Message) + } else { + log.Errorf("unexpected controller response, ContentType: (%v)", msg.ContentType) + return authError + } + + case <-time.After(5 * time.Second): + return errors.New("timeout while unbinding") + } +} + diff --git a/fabric/xgress/transmit_buffer.go b/fabric/xgress/transmit_buffer.go new file mode 100644 index 000000000..a78c6fabb --- /dev/null +++ b/fabric/xgress/transmit_buffer.go @@ -0,0 +1,61 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/emirpasic/gods/trees/btree" + "github.com/emirpasic/gods/utils" +) + +type TransmitBuffer struct { + tree *btree.Tree + sequence int32 +} + +func NewTransmitBuffer() *TransmitBuffer { + return &TransmitBuffer{ + tree: btree.NewWith(10240, utils.Int32Comparator), + sequence: -1, + } +} + +func (buffer *TransmitBuffer) ReceiveUnordered(payload *Payload) { + if payload.GetSequence() > buffer.sequence { + buffer.tree.Put(payload.GetSequence(), payload) + } +} + +func (buffer *TransmitBuffer) ReadyForTransmit() []*Payload { + var ready []*Payload + + if buffer.tree.LeftKey() != nil { + nextSequence := buffer.tree.LeftKey().(int32) + for nextSequence == buffer.sequence+1 { + payload := buffer.tree.LeftValue().(*Payload) + buffer.tree.Remove(nextSequence) + buffer.sequence = nextSequence + + ready = append(ready, payload) + + if buffer.tree.Size() > 0 { + nextSequence = buffer.tree.LeftKey().(int32) + } + } + } + + return ready +} diff --git a/fabric/xgress/xgress.go b/fabric/xgress/xgress.go new file mode 100644 index 000000000..e3b25835b --- /dev/null +++ b/fabric/xgress/xgress.go @@ -0,0 +1,361 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress + +import ( + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/util/concurrenz" + "github.com/netfoundry/ziti-foundation/util/info" + "fmt" + "github.com/michaelquigley/pfxlog" + "io" + "math/rand" + "sync" + "time" +) + +const ( + HeaderKeyUUID = 0 +) + +type Address string + +type XgressListener interface { + Listen(address string, bindHandler BindHandler) error +} + +type XgressDialer interface { + Dial(destination string, sessionId *identity.TokenId, address Address, bindHandler BindHandler) error +} + +type XgressFactory interface { + CreateListener(optionsData XgressOptionsData) (XgressListener, error) + CreateDialer(optionsData XgressOptionsData) (XgressDialer, error) +} + +type XgressOptionsData map[interface{}]interface{} + +// The BindHandlers are invoked to install the appropriate handlers. +// +type BindHandler interface { + HandleXgressBind(sessionId *identity.TokenId, address Address, originator Originator, x *Xgress) +} + +// ReceiveHandler is invoked by an xgress whenever data is received from the connected peer. Generally a ReceiveHandler +// is implemented to connect the xgress to a data plane data transmission system. +// +type ReceiveHandler interface { + // HandleXgressReceive is invoked when data is received from the connected xgress peer. + // + HandleXgressReceive(payload *Payload, x *Xgress) +} + +// CloseHandler is invoked by an xgress when the connected peer terminates the communication. +// +type CloseHandler interface { + // HandleXgressClose is invoked when the connected peer terminates the communication. + // + HandleXgressClose(x *Xgress) +} + +// PeekHandler allows registering watcher to react to data flowing an xgress instance +type PeekHandler interface { + Rx(x *Xgress, payload *Payload) + Tx(x *Xgress, payload *Payload) + Close(x *Xgress) +} + +type Connection interface { + io.Closer + LogContext() string + ReadPayload() ([]byte, map[uint8][]byte, error) + WritePayload([]byte, map[uint8][]byte) (int, error) +} + +type Xgress struct { + sessionId *identity.TokenId + address Address + peer Connection + originator Originator + options *Options + txQueue chan *Payload + txBuffer *TransmitBuffer + rxSequence int32 + rxSequenceLock sync.Mutex + receiveHandler ReceiveHandler + payloadBuffer *PayloadBuffer + closed concurrenz.AtomicBoolean + closeHandler CloseHandler + peekHandlers []PeekHandler +} + +func NewXgress(sessionId *identity.TokenId, address Address, peer Connection, originator Originator, options *Options) *Xgress { + return &Xgress{ + sessionId: sessionId, + address: address, + peer: peer, + originator: originator, + options: options, + txQueue: make(chan *Payload), + txBuffer: NewTransmitBuffer(), + rxSequence: 0, + } +} + +func (txg *Xgress) SessionId() *identity.TokenId { + return txg.sessionId +} + +func (txg *Xgress) Address() Address { + return txg.address +} + +func (txg *Xgress) Originator() Originator { + return txg.originator +} + +func (txg *Xgress) IsTerminator() bool { + return txg.originator == Terminator +} + +func (txg *Xgress) SetReceiveHandler(receiveHandler ReceiveHandler) { + txg.receiveHandler = receiveHandler +} + +func (txg *Xgress) SetPayloadBuffer(payloadBuffer *PayloadBuffer) { + txg.payloadBuffer = payloadBuffer +} + +func (txg *Xgress) SetCloseHandler(closeHandler CloseHandler) { + txg.closeHandler = closeHandler +} + +func (txg *Xgress) AddPeekHandler(peekHandler PeekHandler) { + txg.peekHandlers = append(txg.peekHandlers, peekHandler) +} + +func (txg *Xgress) Start() { + go txg.tx() + go txg.rx() +} + +func (txg *Xgress) Label() string { + return fmt.Sprintf("{s/%s|@/%s}<%s>", txg.sessionId.Token, string(txg.address), txg.originator.String()) +} + +func (txg *Xgress) GetEndSession() *Payload { + endSession := &Payload{ + Header: Header{ + SessionId: txg.sessionId.Token, + flags: SetOriginatorFlag(uint32(PayloadFlagSessionEnd), txg.originator), + }, + Sequence: txg.nextReceiveSequence(), + Data: nil, + } + return endSession +} + +func (txg *Xgress) CloseTimeout(duration time.Duration) { + go txg.closeTimeoutHandler(duration) +} + +func (txg *Xgress) Close() { + log := pfxlog.ContextLogger(txg.Label()) + log.Debug("closing xgress peer") + if err := txg.peer.Close(); err != nil { + log.WithError(err).Warn("error while closing xgress peer") + } + + if txg.closed.CompareAndSwap(false, true) { + log.Debug("closing tx queue") + close(txg.txQueue) + + if txg.options.Retransmission && txg.payloadBuffer != nil { + txg.payloadBuffer.Close() + } + + for _, peekHandler := range txg.peekHandlers { + peekHandler.Close(txg) + } + + if txg.closeHandler != nil { + txg.closeHandler.HandleXgressClose(txg) + } else { + pfxlog.ContextLogger(txg.Label()).Warn("no close handler") + } + } else { + log.Debug("xgress already closed, skipping close") + } +} + +func (txg *Xgress) Closed() bool { + return txg.closed.Get() +} + +func (txg *Xgress) SendPayload(payload *Payload) error { + defer func() { + if r := recover(); r != nil { + pfxlog.ContextLogger(txg.Label()).WithFields(payload.GetLoggerFields()). + WithField("error", r).Error("send on closed channel") + return + } + }() + + if payload.IsSessionEndFlagSet() { + pfxlog.ContextLogger(txg.Label()).Error("received end of session Payload") + } + + if !txg.closed.Get() { + pfxlog.ContextLogger(txg.Label()).WithFields(payload.GetLoggerFields()).Debug("queuing to txQueue") + txg.txQueue <- payload + } + return nil +} + +func (txg *Xgress) SendAcknowledgement(acknowledgement *Acknowledgement) error { + if txg.options.Retransmission && txg.payloadBuffer != nil { + // if we have xgress <-> xgress in a single router, they will share a Payload buffer, as they share + // a session and can get caught in deadlock if we don't dispatch to a new goroutine here + go txg.payloadBuffer.ReceiveAcknowledgement(acknowledgement) + } + return nil +} + +func (txg *Xgress) tx() { + log := pfxlog.ContextLogger(txg.Label()) + + log.Debug("started") + defer log.Debug("exited") + + for { + select { + case inPayload := <-txg.txQueue: + if inPayload != nil && !inPayload.IsSessionEndFlagSet() { + payloadLogger := log.WithFields(inPayload.GetLoggerFields()) + if !txg.options.RandomDrops || rand.Int31n(txg.options.Drop1InN) != 1 { + payloadLogger.Debug("adding to transmit buffer") + txg.txBuffer.ReceiveUnordered(inPayload) + if txg.options.Retransmission && txg.payloadBuffer != nil { + payloadLogger.Debug("acknowledging") + txg.payloadBuffer.AcknowledgePayload(inPayload) + } + } else { + payloadLogger.Error("drop!") + } + + ready := txg.txBuffer.ReadyForTransmit() + for _, outPayload := range ready { + outPayloadLogger := log.WithFields(outPayload.GetLoggerFields()) + for _, peekHandler := range txg.peekHandlers { + peekHandler.Tx(txg, outPayload) + } + n, err := txg.peer.WritePayload(outPayload.Data, outPayload.Headers) + if err != nil { + outPayloadLogger.Warnf("write failed (%s)", err) + } else { + outPayloadLogger.Debugf("sent (#%d) [%s]", outPayload.GetSequence(), info.ByteCount(int64(n))) + } + } + + if len(ready) < 1 { + payloadLogger.Debug("queued transmit") + } + + } else { + return + } + } + } +} + +func (txg *Xgress) rx() { + log := pfxlog.ContextLogger(txg.Label()) + + log.Debug("started") + defer log.Warn("exited") + + defer func() { + if r := recover(); r != nil { + log.Errorf("send on closed channel. error: (%v)", r) + return + } + }() + defer txg.Close() + + for { + buffer, headers, err := txg.peer.ReadPayload() + log.Debugf("read: %v bytes read", len(buffer)) + n := len(buffer) + + // if we got an EOF, but also some data, ignore the EOF, next read we'll get 0, EOF + if err != nil && (n == 0 || err != io.EOF) { + if err == io.EOF { + log.Debugf("EOF, exiting xgress.rx loop") + } else { + log.Warnf("read failed (%s)", err) + } + + return + } + if n < 1 && !txg.closed.Get() { + continue + } + + if !txg.closed.Get() { + payload := &Payload{ + Header: Header{ + SessionId: txg.sessionId.Token, + flags: SetOriginatorFlag(0, txg.originator), + }, + Sequence: txg.nextReceiveSequence(), + Data: buffer[:n], + Headers: headers, + } + payloadLogger := log.WithFields(payload.GetLoggerFields()) + + if txg.options.Retransmission && txg.payloadBuffer != nil { + payloadLogger.Debug("buffering payload") + txg.payloadBuffer.BufferPayload(payload) + } + + for _, peekHandler := range txg.peekHandlers { + peekHandler.Rx(txg, payload) + } + + txg.receiveHandler.HandleXgressReceive(payload, txg) + + payloadLogger.Debugf("received [%s]", info.ByteCount(int64(n))) + } else { + return + } + } +} + +func (txg *Xgress) nextReceiveSequence() int32 { + txg.rxSequenceLock.Lock() + defer txg.rxSequenceLock.Unlock() + + next := txg.rxSequence + txg.rxSequence++ + + return next +} + +func (txg *Xgress) closeTimeoutHandler(duration time.Duration) { + time.Sleep(duration) + txg.Close() +} diff --git a/fabric/xgress_proxy/connection.go b/fabric/xgress_proxy/connection.go new file mode 100644 index 000000000..38c74a3ca --- /dev/null +++ b/fabric/xgress_proxy/connection.go @@ -0,0 +1,41 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_proxy + +import "github.com/netfoundry/ziti-foundation/transport" + +type proxyXgressConnection struct { + transport.Connection +} + +func (c *proxyXgressConnection) LogContext() string { + return c.Detail().String() +} + +func (c *proxyXgressConnection) ReadPayload() ([]byte, map[uint8][]byte, error) { + buffer := make([]byte, 10240) + n, err := c.Reader().Read(buffer) + return buffer[:n], nil, err +} + +func (c *proxyXgressConnection) Write(p []byte) (n int, err error) { + return c.Writer().Write(p) +} + +func (c *proxyXgressConnection) WritePayload(p []byte, headers map[uint8][]byte) (n int, err error) { + return c.Writer().Write(p) +} \ No newline at end of file diff --git a/fabric/xgress_proxy/factory.go b/fabric/xgress_proxy/factory.go new file mode 100644 index 000000000..f442834cc --- /dev/null +++ b/fabric/xgress_proxy/factory.go @@ -0,0 +1,49 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_proxy + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" +) + +func NewFactory(id *identity.TokenId, ctrl xgress.CtrlChannel) xgress.XgressFactory { + return &factory{id: id, ctrl: ctrl} +} + +func (factory *factory) CreateListener(optionsData xgress.XgressOptionsData) (xgress.XgressListener, error) { + options := xgress.LoadOptions(optionsData) + service := "" + if value, found := optionsData["service"]; found { + service = value.(string) + } else { + return nil, fmt.Errorf("missing 'service' configuration option") + } + return newListener(factory.id, factory.ctrl, options, service), nil +} + +func (factory *factory) CreateDialer(optionsData xgress.XgressOptionsData) (xgress.XgressDialer, error) { + return nil, fmt.Errorf("not implemented") +} + +type factory struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + diff --git a/fabric/xgress_proxy/listener.go b/fabric/xgress_proxy/listener.go new file mode 100644 index 000000000..4dd33415e --- /dev/null +++ b/fabric/xgress_proxy/listener.go @@ -0,0 +1,76 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_proxy + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "fmt" + "github.com/michaelquigley/pfxlog" +) + +func newListener(id *identity.TokenId, ctrl xgress.CtrlChannel, options *xgress.Options, service string) xgress.XgressListener { + return &listener{ + id: id, + ctrl: ctrl, + options: options, + service: service, + } +} + +func (listener *listener) Listen(address string, bindHandler xgress.BindHandler) error { + txAddress, err := transport.ParseAddress(address) + if err != nil { + return fmt.Errorf("cannot listen on invalid address [%s] (%s)", address, err) + } + + incomingPeers := make(chan transport.Connection) + go txAddress.MustListen("tcp", listener.id, incomingPeers) + go func() { + for { + select { + case peer := <-incomingPeers: + if peer != nil { + go listener.handleConnect(peer, bindHandler) + } else { + return + } + } + } + }() + + return nil +} + +func (listener *listener) handleConnect(peer transport.Connection, bindHandler xgress.BindHandler) { + conn := &proxyXgressConnection{peer} + log := pfxlog.ContextLogger(conn.LogContext()) + request := &xgress.Request{ServiceId: listener.service} + response := xgress.CreateSession(listener.ctrl, conn, request, bindHandler, listener.options) + if !response.Success { + log.Errorf("error creating session (%s)", response.Message) + _ = peer.Close() + } +} + +type listener struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options + service string +} diff --git a/fabric/xgress_transport/client.go b/fabric/xgress_transport/client.go new file mode 100644 index 000000000..3920e25a4 --- /dev/null +++ b/fabric/xgress_transport/client.go @@ -0,0 +1,50 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_transport + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "errors" +) + +// ClientDial dials the given xgress address and handles authentication, returning an authed connection or an error +func ClientDial(addr transport.Address, id *identity.TokenId, serviceId *identity.TokenId) (transport.Connection, error) { + peer, err := addr.Dial("i/"+id.Token, id) + if err != nil { + return nil, err + } + + request := &xgress.Request{ + Id: id.Token, + ServiceId: serviceId.Token, + } + err = xgress.SendRequest(request, peer.Writer()) + if err != nil { + return nil, err + } + response, err := xgress.ReceiveResponse(peer) + if err != nil { + return nil, err + } + if !response.Success { + return nil, errors.New(response.Message) + } + + return peer, nil +} diff --git a/fabric/xgress_transport/connection.go b/fabric/xgress_transport/connection.go new file mode 100644 index 000000000..1436d15a6 --- /dev/null +++ b/fabric/xgress_transport/connection.go @@ -0,0 +1,43 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_transport + +import ( + "github.com/netfoundry/ziti-foundation/transport" +) + +type transportXgresscConn struct { + transport.Connection +} + +func (c *transportXgresscConn) LogContext() string { + return c.Detail().String() +} + +func (c *transportXgresscConn) ReadPayload() ([]byte, map[uint8][]byte, error) { + buffer := make([]byte, 10240) + n, err := c.Reader().Read(buffer) + return buffer[:n], nil, err +} + +func (c *transportXgresscConn) Write(p []byte) (n int, err error) { + return c.Writer().Write(p) +} + +func (c *transportXgresscConn) WritePayload(p []byte, headers map[uint8][]byte) (n int, err error) { + return c.Writer().Write(p) +} diff --git a/fabric/xgress_transport/dialer.go b/fabric/xgress_transport/dialer.go new file mode 100644 index 000000000..ce0781616 --- /dev/null +++ b/fabric/xgress_transport/dialer.go @@ -0,0 +1,57 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_transport + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "fmt" +) + +type dialer struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + +func newDialer(id *identity.TokenId, ctrl xgress.CtrlChannel, options *xgress.Options) (xgress.XgressDialer, error) { + txd := &dialer{ + id: id, + ctrl: ctrl, + options: options, + } + return txd, nil +} + +func (txd *dialer) Dial(destination string, sessionId *identity.TokenId, address xgress.Address, bindHandler xgress.BindHandler) error { + txDestination, err := transport.ParseAddress(destination) + if err != nil { + return fmt.Errorf("cannot dial on invalid address [%s] (%s)", destination, err) + } + + peer, err := txDestination.Dial("x/"+sessionId.Token, sessionId) + if err != nil { + return err + } + + conn := &transportXgresscConn{peer} + x := xgress.NewXgress(sessionId, address, conn, xgress.Terminator, txd.options) + bindHandler.HandleXgressBind(sessionId, address, xgress.Terminator, x) + + return nil +} diff --git a/fabric/xgress_transport/factory.go b/fabric/xgress_transport/factory.go new file mode 100644 index 000000000..d2f9b4528 --- /dev/null +++ b/fabric/xgress_transport/factory.go @@ -0,0 +1,43 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_transport + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type factory struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + +// NewFactory returns a new Transport Xgress factory +func NewFactory(id *identity.TokenId, ctrl xgress.CtrlChannel) xgress.XgressFactory { + return &factory{id: id, ctrl: ctrl} +} + +func (factory *factory) CreateListener(optionsData xgress.XgressOptionsData) (xgress.XgressListener, error) { + options := xgress.LoadOptions(optionsData) + return newListener(factory.id, factory.ctrl, options), nil +} + +func (factory *factory) CreateDialer(optionsData xgress.XgressOptionsData) (xgress.XgressDialer, error) { + options := xgress.LoadOptions(optionsData) + return newDialer(factory.id, factory.ctrl, options) +} diff --git a/fabric/xgress_transport/listener.go b/fabric/xgress_transport/listener.go new file mode 100644 index 000000000..00160ffb7 --- /dev/null +++ b/fabric/xgress_transport/listener.go @@ -0,0 +1,88 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_transport + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "fmt" + "github.com/michaelquigley/pfxlog" +) + +type listener struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + +func newListener(id *identity.TokenId, ctrl xgress.CtrlChannel, options *xgress.Options) xgress.XgressListener { + return &listener{ + id: id, + ctrl: ctrl, + options: options, + } +} + +func (listener *listener) Listen(address string, bindHandler xgress.BindHandler) error { + txAddress, err := transport.ParseAddress(address) + if err != nil { + return fmt.Errorf("cannot listen on invalid address [%s] (%s)", address, err) + } + + incomingPeers := make(chan transport.Connection) + go txAddress.MustListen("tcp", listener.id, incomingPeers) + go func() { + for { + select { + case peer := <-incomingPeers: + if peer != nil { + go listener.handleConnect(peer, bindHandler) + } else { + return + } + } + } + }() + + return nil +} + +func (listener *listener) handleConnect(peer transport.Connection, bindHandler xgress.BindHandler) { + conn := &transportXgresscConn{peer} + log := pfxlog.ContextLogger(conn.LogContext()) + + request, err := xgress.ReceiveRequest(peer) + if err == nil { + response := xgress.CreateSession(listener.ctrl, conn, request, bindHandler, listener.options) + err = xgress.SendResponse(response, peer.Writer()) + if err != nil { + log.Errorf("error sending response (%s)", err) + } + + if err != nil || !response.Success { + if err := peer.Close(); err != nil { + log.Errorf("error closing transport connection (%s)", err) + } + } + } else { + log.Errorf("error receiving request from peer (%s)", err) + if err := peer.Close(); err != nil { + log.Errorf("error closing transport connection (%s)", err) + } + } +} diff --git a/fabric/xgress_udp/address.go b/fabric/xgress_udp/address.go new file mode 100644 index 000000000..287960182 --- /dev/null +++ b/fabric/xgress_udp/address.go @@ -0,0 +1,64 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_udp + +import ( + "errors" + "fmt" + "strings" +) + +var supportedNetworks = map[string]string{ + "udp": "", + "udp4": "", + "udp6": "", + "unixgram": "", +} + +type packetAddress struct { + network string + address string +} + +func (pa *packetAddress) String() string { + return fmt.Sprintf("packetAddress{network=%v, addr=%v}", pa.network, pa.address) +} + +func (pa *packetAddress) Network() string { + return pa.network +} + +func (pa *packetAddress) Address() string { + return pa.address +} + +func parseAddress(s string) (*packetAddress, error) { + tokens := strings.Split(s, ":") + if len(tokens) < 2 { + return nil, errors.New("invalid format") + } + + network := tokens[0] + + if _, ok := supportedNetworks[network]; !ok { + return nil, fmt.Errorf("unsupported network '%s'", network) + } + + address := strings.Join(tokens[1:], ":") + + return &packetAddress{network, address}, nil +} diff --git a/fabric/xgress_udp/connection.go b/fabric/xgress_udp/connection.go new file mode 100644 index 000000000..20ea85979 --- /dev/null +++ b/fabric/xgress_udp/connection.go @@ -0,0 +1,43 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_udp + +import ( + "github.com/netfoundry/ziti-foundation/transport/udp" + "net" +) + +type xgressPacketConn struct { + net.Conn +} + +func (xpc *xgressPacketConn) LogContext() string { + return xpc.RemoteAddr().String() +} + +func (xpc *xgressPacketConn) ReadPayload() ([]byte, map[uint8][]byte, error) { + buffer := make([]byte, udp.MaxPacketSize) + n, err := xpc.Read(buffer) + if err != nil { + return nil, nil, err + } + return buffer[:n], nil, nil +} + +func (xpc *xgressPacketConn) WritePayload(p []byte, headers map[uint8][]byte) (n int, err error) { + return xpc.Write(p) +} \ No newline at end of file diff --git a/fabric/xgress_udp/dialer.go b/fabric/xgress_udp/dialer.go new file mode 100644 index 000000000..e5910e29a --- /dev/null +++ b/fabric/xgress_udp/dialer.go @@ -0,0 +1,62 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_udp + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "fmt" + "github.com/michaelquigley/pfxlog" + "net" +) + +type dialer struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + +func newDialer(id *identity.TokenId, ctrl xgress.CtrlChannel, options *xgress.Options) (*dialer, error) { + txd := &dialer{ + id: id, + ctrl: ctrl, + options: options, + } + return txd, nil +} + +func (txd *dialer) Dial(destination string, sessionId *identity.TokenId, address xgress.Address, bindHandler xgress.BindHandler) error { + pfxlog.Logger().Infof("Parsing %v for xgress address: %v", destination, address) + packetAddress, err := parseAddress(destination) + if err != nil { + return fmt.Errorf("cannot dial on invalid address [%s] (%s)", destination, err) + } + + pfxlog.Logger().Infof("Dialing packet address %v", packetAddress) + conn, err := net.Dial(packetAddress.Network(), packetAddress.Address()) + if err != nil { + return err + } + + pfxlog.Logger().Infof("Bound on '%v'", conn.LocalAddr()) + + xgConn := &xgressPacketConn{conn} + x := xgress.NewXgress(sessionId, address, xgConn, xgress.Terminator, txd.options) + bindHandler.HandleXgressBind(sessionId, address, xgress.Terminator, x) + + return nil +} diff --git a/fabric/xgress_udp/factory.go b/fabric/xgress_udp/factory.go new file mode 100644 index 000000000..b225fd0b3 --- /dev/null +++ b/fabric/xgress_udp/factory.go @@ -0,0 +1,45 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_udp + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" +) + +type factory struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options +} + +// NewFactory construct a new UDP Xgress factory instance +func NewFactory(id *identity.TokenId, ctrl xgress.CtrlChannel) xgress.XgressFactory { + return &factory{id: id, ctrl: ctrl} +} + +// CreateListener creates a new UDP Xgress listener +func (factory *factory) CreateListener(optionsData xgress.XgressOptionsData) (xgress.XgressListener, error) { + options := xgress.LoadOptions(optionsData) + return newListener(factory.id, factory.ctrl, options), nil +} + +// CreateDialer creates a new UDP Xgress dialer +func (factory *factory) CreateDialer(optionsData xgress.XgressOptionsData) (xgress.XgressDialer, error) { + options := xgress.LoadOptions(optionsData) + return newDialer(factory.id, factory.ctrl, options) +} diff --git a/fabric/xgress_udp/listener.go b/fabric/xgress_udp/listener.go new file mode 100644 index 000000000..5a51dee1d --- /dev/null +++ b/fabric/xgress_udp/listener.go @@ -0,0 +1,283 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xgress_udp + +import ( + "github.com/netfoundry/ziti-fabric/fabric/xgress" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport/udp" + "fmt" + "github.com/michaelquigley/pfxlog" + "io" + "net" + "time" +) + +const ( + defaultTimeoutInterval = time.Minute +) + +type listener struct { + id *identity.TokenId + ctrl xgress.CtrlChannel + options *xgress.Options + address string + bindHandler xgress.BindHandler + conn net.PacketConn + dataChan chan *packetData + eventChan chan packetEvent + sessions map[string]*packetSession +} + +func newListener(id *identity.TokenId, ctrl xgress.CtrlChannel, options *xgress.Options) *listener { + return &listener{ + id: id, + ctrl: ctrl, + options: options, + dataChan: make(chan *packetData, 10), + eventChan: make(chan packetEvent, 10), + sessions: make(map[string]*packetSession), + } +} + +func (listener *listener) Listen(address string, bindHandler xgress.BindHandler) error { + listener.address = address + listener.bindHandler = bindHandler + + pfxlog.Logger().Infof("Parsing xgress address: %v", address) + packetAddress, err := parseAddress(address) + if err != nil { + return fmt.Errorf("cannot listen on invalid address [%s] (%s)", address, err) + } + + pfxlog.Logger().Infof("Dialing packet address %v", packetAddress) + conn, err := net.ListenPacket(packetAddress.Network(), packetAddress.Address()) + if err != nil { + return err + } + + listener.conn = conn + go listener.relayIncomingPackets() + go listener.rx() + + return nil +} + +func (listener *listener) close() { + logger := pfxlog.ContextLogger(listener.address) + if listener.conn != nil { + if err := listener.conn.Close(); err != nil { + logger.Errorf("failure closing packet conn. (%v)", err) + } + } +} + +func (listener *listener) relayIncomingPackets() { + defer listener.close() + + logger := pfxlog.ContextLogger(listener.address) + + for { + buf := make([]byte, udp.MaxPacketSize) + logger.Debugf("Trying to read next packet") + bytesRead, addr, err := listener.conn.ReadFrom(buf) + logger.Debugf("Packet read complete: %v bytes read", bytesRead) + + if bytesRead > 0 { + pd := &packetData{ + buffer: buf[:bytesRead], + source: addr, + } + listener.dataChan <- pd + } + + if err != nil { + logger := pfxlog.ContextLogger(listener.address) + logger.Error(err) + } + } +} + +func (listener *listener) rx() { + logger := pfxlog.ContextLogger(listener.address) + + sessionScanTimer := time.Tick(time.Second * 10) + + for { + select { + case data := <-listener.dataChan: + logger.Debugf("Handling data. Bytes %v from source %v", len(data.buffer), data.source) + sessionId := data.source.String() + session, present := listener.sessions[sessionId] + if !present { + session = &packetSession{ + listener: listener, + readC: make(chan []byte, 10), + addr: data.source, + sessionState: sessionStateNew, + timeoutIntervalNanos: defaultTimeoutInterval.Nanoseconds(), + } + session.MarkActivity() + listener.sessions[sessionId] = session + logger.Debugf("No session present. Authenticating session for %v", data.source) + go listener.handleConnect(data.buffer, session) + } else if session.sessionState == sessionStateEstablished { + logger.Debugf("Session established for %v, forwarding data", data.source) + session.MarkActivity() + session.readC <- data.buffer + logger.Debugf("Session established for %v. Data forwarded", data.source) + } + case event := <-listener.eventChan: + event.handle(listener) + case tick := <-sessionScanTimer: + nowNanos := tick.UnixNano() + for _, session := range listener.sessions { + if session.timeoutNanos < nowNanos { + _ = session.Close() // always returns nil + } + } + } + } +} + +type sessionState uint8 + +const ( + sessionStateNew sessionState = iota + sessionStateEstablished +) + +type packetEvent interface { + handle(listener *listener) +} + +type packetSession struct { + listener *listener + readC chan []byte + addr net.Addr + sessionState sessionState + timeoutIntervalNanos int64 + timeoutNanos int64 + closed bool +} + +func (session *packetSession) getSessionId() string { + return session.addr.String() +} + +func (session *packetSession) ReadPayload() ([]byte, map[uint8][]byte, error) { + select { + case buffer, chanOpen := <-session.readC: + if !chanOpen { + return buffer, nil, io.EOF + } + return buffer, nil, nil + } +} + +func (session *packetSession) Write(p []byte) (n int, err error) { + session.listener.eventChan <- (*sessionUpdateEvent)(session) // queues session timeout to be updated + return session.listener.conn.WriteTo(p, session.addr) +} + +func (session *packetSession) WritePayload(p []byte, headers map[uint8][]byte) (n int, err error) { + return session.Write(p) +} + +func (session *packetSession) Close() error { + session.listener.eventChan <- (*sessionCloseEvent)(session) // queues session to be removed + return nil +} + +func (session *packetSession) LogContext() string { + return session.addr.String() +} + +func (session *packetSession) MarkActivity() { + session.timeoutNanos = time.Now().UnixNano() + session.timeoutIntervalNanos +} + +func (listener *listener) handleConnect(initialRequest []byte, session *packetSession) { + log := pfxlog.ContextLogger(session.addr.String()) + + var response *xgress.Response + + request, err := xgress.RequestFromJSON(initialRequest) + if err != nil { + log.Error(err) + response = &xgress.Response{Success: false, Message: "invalid request"} + } else { + response = xgress.CreateSession(listener.ctrl, session, request, listener.bindHandler, listener.options) + } + + listener.eventChan <- &sessionResponse{addr: session.addr, response: response} +} + +type sessionUpdateEvent packetSession + +func (session *sessionUpdateEvent) handle(listener *listener) { + (*packetSession)(session).MarkActivity() +} + +type sessionCloseEvent packetSession + +func (closeEvent *sessionCloseEvent) handle(listener *listener) { + // Note: The Xgress will close when EOF is returned from a read. That will also cause the session to be closed + // The session packet will return EOF from a read when the session.readC is closed + session := (*packetSession)(closeEvent) + if !session.closed { + close(session.readC) + delete(listener.sessions, session.getSessionId()) + session.closed = true + } +} + +type packetData struct { + buffer []byte + source net.Addr +} + +type sessionResponse struct { + addr net.Addr + response *xgress.Response +} + +func (response *sessionResponse) handle(listener *listener) { + logger := pfxlog.ContextLogger(listener.address) + + sessionId := response.addr.String() + session, present := listener.sessions[sessionId] + respMsg := response.response + if !present { + // session timed out or some other unexpected failure + respMsg = &xgress.Response{Success: false, Message: "timeout"} + session = &packetSession{listener: listener, addr: response.addr} + logger.Debugf("Session %v not found for response", sessionId) + } else if response.response.Success { + session.sessionState = sessionStateEstablished + logger.Debugf("Session %v found for success response. Marking established", sessionId) + } else { + logger.Debugf("Session %v found for failure response. Removing session", sessionId) + _ = session.Close() // always returns nil + } + logger.Debugf("Sending response to client for %v", sessionId) + err := xgress.SendResponse(respMsg, session) + logger.Debugf("Response to client for %v sent", sessionId) + if err != nil { + logger.Errorf("failure sending response (%v)", err) + } +} diff --git a/fabric/xmgmt/xmgmt.go b/fabric/xmgmt/xmgmt.go new file mode 100644 index 000000000..dcb88c8a7 --- /dev/null +++ b/fabric/xmgmt/xmgmt.go @@ -0,0 +1,29 @@ +/* + Copyright 2019 Netfoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package xmgmt + +import ( + "github.com/netfoundry/ziti-foundation/channel2" + "github.com/netfoundry/ziti-foundation/config" +) + +type Xmgmt interface { + config.Subconfig + channel2.BindHandler + Enabled() bool + Run(mgmt channel2.Channel, done chan struct{}) error +}