在本指南中,我们将展示两个名为 Alice 和 Bob 的程序。 Alice 和 Bob 将通过网络、云服务、Kafka 相互发送消息。它们将相互进行身份验证,并具有加密保证,以端到端地保护其消息的完整性、真实性和机密性。 Kafka 实例、中间云服务和网络上的攻击者将无法看到或更改途中消息的内容。 Kafka 中的应用程序数据将被加密。现代分布式应用程序在高度动态的环境中运行。基础设施自动化、多个云或数据中心中的微服务、移动劳动力、物联网和边缘计算意味着机器和应用程序不断地离开和进入网络边界。应用程序架构师已经了解到,他们必须降低他们的信任度网络边界和基础设施。我们的应用程序的漏洞表面不能包括可能在同一个多孔网络边界内运行的所有代码。该表面太大、太动态且通常超出应用程序开发人员的控制范围。相反,应用程序必须控制自己数据的安全性和可靠性。为此,通过网络接收到的所有消息都必须证明是谁发送的,并表明它们没有被篡改或伪造。可以剥夺 Alice 和 Bob 依赖传入消息的完整性和真实性的能力的现代应用程序的另一个方面是中间服务,例如我们下面示例中的云服务。分布式应用程序中的数据很少通过单个点对点传输连接进行交换。应用程序消息通常通过复杂的、多跳的、多协议的路由流动——跨数据中心、通过队列和缓存、通过网关和代理——在到达他们的最终目的地之前。通常,当信息或命令通过中间服务交换时,中间人能够读取正在交换的消息、更新路由消息、从未发送的创建消息和删除(从不传递)实际发送的消息。 Alice 和 Bob 完全依赖于这些中介的安全性。如果中介的防御受到损害,我们的应用程序也会受到损害。
传输层安全协议无法保护应用程序消息,因为它们的保护受到底层传输连接的长度和持续时间的限制。如果 Alice 和 Bob 之间存在中介,则 Alice 和中介之间的传输连接与 Bob 和中介之间的传输连接完全不同。在微服务、物联网和边缘计算等环境中,通常有很多这样的中介。我们的应用程序的漏洞表面迅速增长并变得无法管理。 Ockam 是一套编程库,可让应用程序轻松创建任意数量的轻量级、相互验证、端到端加密安全通道。这些通道使用加密技术来保证消息的端到端完整性、真实性和机密性。应用程序可以使用 Ockam 安全通道来强制对其分布式部件之间作为消息流动的命令、数据、配置、机器学习模型和软件更新进行最低特权访问。中间服务和受损软件(可能在同一网络边界内运行)不再对我们的应用程序消息具有隐式 CRUD 权限。取而代之的是,我们对访问权限进行了精细控制——立即检测到篡改或伪造动态数据。通过端到端的安全通道,我们可以使应用程序的漏洞面变得非常小。让我们通过云服务,通过 Kafka,使用 Ockam 在 Alice 和 Bob 之间建立端到端的受保护通信。为了建立安全通道,我们需要能够在两端之间双向发送消息。为此,我们将使用两个 Kafka 主题,为简单起见,我们将使用单个分区主题来完成此操作。
我们的目标是使消息交换安全并保证至少传递一次。我们将运行两个名为 Alice 和 Bob 的程序。我们希望 Bob 创建一个安全通道侦听器,并要求 Alice 与该侦听器发起安全握手(经过身份验证的密钥交换)。我们可以想象 Bob 和 Alice 在两台不同的计算机上运行,并且这次握手必须通过 Internet 进行。我们还将假设 Bob 在一个私有网络中运行,并且无法打开暴露在 Internet 上的公共端口。相反,Bob 在一个 Ockam 节点上注册了一个双向的 Ockam 流。这个 Ockam Stream 被配置为在 Kafka 中存储数据。我们将使用的 Ockam 节点在 Ockam Hub 中作为云服务运行。该节点的 TCP 地址为 1.node.ockam.network:4000,它提供了两个与 Kafka 相关的服务:stream_kafka 和 stream_kafka_index。 Bob 程序创建了一个安全通道侦听器来接受开始 AuthenticatedKey 交换的请求。它通过 TCP 连接到位于 1.node.ockam.network:4000 的云节点,并在该云节点上创建双向的、由 Kafka 支持的 Ockam 流。所有到达该流的消息都将使用 Bob 作为客户端创建的 TCP 连接转发给 Bob。 Bob 还启动了一个 Echoer 工作程序,打印它收到的任何消息,并在其返回路由上回显。 Bob 程序将打印两个流名称,发送者和接收者,这是 Bob 在云节点上的流地址,将它们复制。
它将停止询问在步骤 2 中打印的 Bob 的流名称。输入它们。这将告诉 Alice,到达 Bob 的路由是通过在“1.node.ockam.network”上注册的流名称。当 Alice 沿着这条路由发送消息时,Ockam 路由层将查看路由中的第一个地址并将消息传递给 TCP 传输。 TCP 传输将通过 TCP 与 cloudnode 连接并将消息传递给它。然后,云节点上的路由层将通过 Kafka 流将消息传递给 Bob。 Kafka 客户端将通过 Bob 之前与云节点创建的 TCP 连接将消息发送给 Bob。来自 Bob 的回复沿着相同的路径返回,整个安全通道握手就是这样完成的。一旦建立了安全通道,Alice 程序将停止并要求您为 Bob 输入一条消息。您输入的任何消息都会通过云节点使用安全通道传递给 Bob。 echoeron Bob 将在同一路径上回显消息,Alice 将打印它。现在我们了解了它是如何工作的,让我们看一下 Rust 中 Alice 和 Bob 程序的代码。
cargo new --lib ockam_kafka && cd ockam_kafka && mkdir examples && echo 'ockam = "*"' >> Cargo.toml && cargo build 如果上述说明在您的机器上不起作用,请提出问题,我们很乐意提供帮助. // examples/bob.rs 使用 ockam ::{route, Context, Entity, Result, SecureChannels, TrustEveryonePolicy, Vault};使用 ockam ::{stream ::Stream, Routed, TcpTransport, Unique, Worker, TCP};结构回声; // 定义一个 Echoer worker,它打印它接收到的任何消息并 // 在返回路由上回显它。#[ockam::worker] impl Worker for Echoer { type Context = Context;类型消息 = 字符串; async fn handle_message( & mut self, ctx: & mut Context, msg: Routed<String>) -> Result<()> { println!( " \n[✓] Address: {}, Received: {}", ctx地址(),味精); // 在其 return_route 上回显消息正文。 ctx。发送(味精。return_route(),味精。正文())。 await }}#[ockam::node] async fn main(ctx: Context) -> Result<()> { // 初始化 TCP 传输。 TcpTransport :: 创建( &ctx)。等待?; // 创建一个 Vault 来安全地存储 Bob 的密钥。让保险库 = 保险库 :: 创建( &ctx)?; // 创建一个实体来代表 Bob。让 mut bob = Entity :: create( &ctx, &vault)?; // 为 Bob 创建一个安全通道侦听器,它将等待请求 // 启动经过身份验证的密钥交换。鲍勃。 create_secure_channel_listener("listener", TrustEveryonePolicy)?; // 运行此程序的计算机可能位于专用网络中, // 无法通过 Internet 访问。 // // 为了允许 Alice 和其他人使用此程序启动端到端安全通道 // 我们作为 TCP 客户端连接到 1.node.ockam.network:4000 并询问 Kafka Add-on // on该节点为我们创建一个双向流。 // // 发送到流和到达流的所有消息都将使用我们作为客户端创建的 TCP 连接进行中继。让 node_in_hub = (TCP, "1.node.ockam.network:4000"); let sender_name = Unique :: with_prefix( "bob-to-alice"); letreceiver_name = Unique :: with_prefix( "alice-to-bob");流 :: new( &ctx)? .流服务(“stream_kafka”)。 index_service( "stream_kafka_index") 。 client_id(Unique :: with_prefix( "bob")) 。连接(路由![node_in_hub],sender_name.clone(),receiver_name.clone())。等待?; println!( " \n[✓] 流客户端在节点上创建:1.node.ockam.network:4000"); println!( " \n流发送者名称为:{}", sender_name); println!( "流接收者名称为:{} \n",receiver_name); // 在地址“echoer”处启动一个 Echoer 类型的工作线程。 // 这个工作者将沿着它的返回路线回显它收到的每条消息。 ctx。 start_worker(“回声”,回声)。等待?; // 我们不会在这里调用 ctx.stop(),这个程序会一直运行,直到你用 Ctrl-C 停止它 Ok(())} // examples/alice.rs 使用 ockam ::{route, Context, Entity,结果、SecureChannels、TrustEveryonePolicy、Vault};使用 ockam ::{stream ::Stream, TcpTransport, Unique, TCP}; use std ::io;#[ockam::node] async fn main( mut ctx: Context) -> Result<()> { // 初始化 TCP 传输。 TcpTransport :: 创建( &ctx)。等待?; // 创建一个 Vault 来安全地存储 Alice 的密钥。让保险库 = 保险库 :: 创建( &ctx)?; // 创建一个实体来代表 Alice。让 mut alice = Entity :: create( &ctx, &vault)?; // 该程序期望 Bob 创建一个双向流, // 将在 Ockam 节点上为他的安全通道侦听器中继消息 // 在 1.node.ockam.network:4000。 // // 从标准输入中,读取 // Bob 的安全通道侦听器的双向流名称。 println!( " \n输入 Bob 的流发送者名称:");让 mut sender_name = String :: new(); io::stdin()。 read_line( & mut sender_name)。 expect("读取标准输入时出错。");让 sender_name = sender_name。修剪(); println!( " \n输入 Bob 的流接收器名称:");让 mut receiver_name = String :: new(); io::stdin()。 read_line( & mutreceiver_name)。 expect("读取标准输入时出错。");让receiver_name =receiver_name。修剪(); // 使用节点的 tcp 地址通过 Kafka 流客户端获取到 Bob 的安全 // 通道侦听器的路由。 let route_to_bob_listener = route![(TCP, "1.node.ockam.network:4000")]; let (sender, _receiver) = Stream :: new( &ctx)? .流服务(“stream_kafka”)。 index_service( "stream_kafka_index") 。 client_id(Unique :: with_prefix( "alice")) 。连接(route_to_bob_listener,receiver_name,sender_name)。等待?; // 作为 Alice,连接到 Bob 的安全通道侦听器,并执行 // 身份验证密钥交换以与 Bob 建立加密的 // 安全通道。让 r = 路线![发件人。克隆(),“听众”];让频道=爱丽丝。 create_secure_channel(r, TrustEveryonePolicy)?; println!( " \n[✓] 端到端加密安全通道建立。\n"); loop { // 从标准输入读取消息。 println!( "为 Bob 的 echoer 输入一条消息:");让 mut message = String :: new(); io::stdin()。 read_line( & mut 消息)。 expect("从标准输入读取错误。");让消息 = 消息。修剪(); // 通过通道将提供的消息发送到 Bob 的 echoer。 ctx。发送(路由![通道。克隆(),“回声”],消息。to_string())。等待?; // 等待接收回声并打印它。让回复 = ctx。接收::<字符串>()。等待?; println!( "Alice 收到了一个回声:{} \n", 回复); // 应该打印“你好奥卡姆!” } // 这个程序会一直运行,直到你用 Ctrl-C 停止它} 我们讨论过,为了有一个小的和可管理的漏洞表面,分布式应用程序必须使用相互认证的、端到端的加密通道。端到端的安全通道协议,从头开始,很复杂,容易出错,并且需要比应用程序团队通常用于解决这个问题的时间更多。在上面的例子中,我们创建了一个相互认证的、端到端的加密通道,通过 Kafka 主题运行,将端到端加密的安全性与 Kafka 的交付保证相结合。 Ockam 将经过验证的加密构建块组合成一组可重用的协议,用于分布式应用程序以进行安全和私密的通信。上面的例子只触及了我们包含在 Ockam 中的工具可能实现的表面。