云架构系列之一-Azure云核心内核系统架构详解

admin 2022年4月2日18:43:38评论50 views字数 26797阅读89分19秒阅读模式

云架构系列之一-Azure云核心内核系统架构详解
更新背景
  • 为什么更新本篇?
目前《鸟哥谈云安全》公众号已经更新了三篇云安全架构、云安全技术和对应的AAG(AWS、Azure、Google)的内容,突然写到云架构了。可能很多读者会带有一些疑问。首先做一下解释,鸟哥对云安全的更多内容会逐步放开,希望读者朋友支持关注,等待好的更多的云安全架构的分享^_^。

其实更新本篇云架构的文章,主要原因还是因为近期花了些时间对微软CEO Satya的书《Hit Refresh》以及Google的《Build Secure and Reliable Systems》进行了深度的阅读,发现了2个重要的洞见:第一个就是在微软CEO Satya的书中,他详细讲解了对于创建Azure过程中的四大问题,其中一个就是Azure的分布式系统的问题,其实Azure的架构也不是一帆风顺的,也是通过Microsoft Bing分布式搜索的架构的前身来沉淀下来的,所以对于Azure来说比较核心和比较保密的信息就是Azure的底层的云分布式操作系统Azure Fabric Controller(本文的主角)。第二个就是Google在安全的书中,反复强调和讲述的逻辑都是再说Google的安全场景,遇到什么样的研发框架、研发流程、研发工具、底层基础设施架构、处理安全事件的联动其他部门的机制和措施、打磨安全工程化、安全架构、安全技术设计思路和解决问题的方法等等,通过这两点我发现了对于云安全架构来说,云底层的架构的技术、工程化、实现方式的重要性。包括Google的Borg(后续会更新)、Azure的Fabric Controller、AWS的离线/软实时分布式操作系统、SOA架构等,因为安全都是在这些基础设施架构上进行安全的构建。例如Amazon CloudAuth、Google BeyondProd等等。其实我个人在研究云原生和基础设施架构上花了非常多的时间和精力,就是想搞清楚人家到底是如何在底层基础设施上来构建安全的。在学习的过程中,还是有了一些不错的收获,还是了解到了非常多的细节知识。所以本文就是把我看到的一些在公开场合比较难获取到的一些底层架构知识来进行分享(声明:此研究仅仅是个人行为,获取的信息也是公开情报获取)。

Azure云平台架构底层设计
一、Azure云平台整体架构
之前在《鸟哥谈云安全-云安全架构连载之一-Azure整体架构及安全亮点详解》中简单介绍了一下Azure的顶层的架构,包括网络架构的设计(Region、AZ、DC数据中心)、Azure服务、Azure集群、Azure操作系统等进行了简单的介绍,其实只是一个初步的分析,如果后面有机会会针对每一个技术域进行详细分析。

二、Azure Cluster集群架构
0、架构背景
在正式开始全盘分析Azure Fabric Controller之前,还是跟读者交代一下,整个Azure的服务(云产品)是如何一步一步的从系统加电->底层操作系统启动->部署Azure Fabric Controller->部署Azure Red Dog Front End->部署Azure服务(云产品)->上线发布给客户上线使用流程。

1、Azure底层操作系统启动流程

云架构系列之一-Azure云核心内核系统架构详解

  • 启动电源;

  • PXE-boot启动维护操作系统;

  • Agent进行格式化硬盘以及通过Windows Deployment Services(WDS)下载Host OS;

  • HostOS采用Sysprep(来进行安全加固配置)等,完成后重新启动;

  • FC Host Agent连接到FC中心;


2、Azure Cluster架构

云架构系列之一-Azure云核心内核系统架构详解

Windows操作系统安装完成之后,就会通过部署对应的集群。把底层多达20个的Rack的上千台服务器构成了DataCenter Cluster集群,同时Azure Cluster也是一个Failover故障转移的一个最小单元,这个集群包含了Fabric Controller、Rack服务器上部署的一些Azure Services服务等;
下图就是Azure的一个Cluster的集群管理的功能(包括管理虚拟机、网络设备配置、存储配置、日志管理、事件等等):

云架构系列之一-Azure云核心内核系统架构详解


3、Azure Fabric Controller

云架构系列之一-Azure云核心内核系统架构详解

每个Cluster集群上都会部署一个Fabric Controller(后续简称FC),并且每个集群都是通过FC来进行管理的,FC主要职责是Blade的管理、服务的部署和声明周期管理、Host操作系统管理、HyperVisor(Hyper-V)管理、虚拟机的管理;可以明显的看到FC是整个Azure云操作系统的“Kernel”内核;

这里可以看到一个对比,传统的服务器包括(Server服务器、Windows Kernel内核、Word和SQL Server应用),到Azure云之后Server服务器对应Azure DataCenter、Windows Kernel对应FC、Word和SQL Server的应用对应ExchangeOnline和SQL Azure;下图就是Fabric Viewer的管理界面;可以简单看到这个集群的状态、集群租户的机器状态、故障状态等等信息

云架构系列之一-Azure云核心内核系统架构详解


4、Azure服务发布流程

云架构系列之一-Azure云核心内核系统架构详解

  • 服务开发:Azure的服务通过VisualStudio SaaS版进行开发,Azure自身的代码全部存储在了SaaS上,SaaS版的功能包括仓库管理、Pipeline发布管理、部署管理、代码管理、Issues问题跟踪等;PS:如果有想研究Azure VS SaaS漏洞的可以在这里下载Azure DevOps Server 2020版进行研究(https://go.microsoft.com/fwlink/?LinkId=2132056);

  • 服务发布:Azure的服务推送到RDFE(Red Dog Front End),RDFE发送到制定Region的FC,FC存储对应的镜像和部署的服务到对应的虚拟机或者裸金属上;


5、Azure服务部署到线上流程

云架构系列之一-Azure云核心内核系统架构详解

  • 资源:确定需要的资源包括CPU、内存、硬盘、网络资源等信息;

  • 准备Nodes节点:创建虚拟机资源、部署Role镜像,启动虚拟机和Roles;

  • 配置网络:动态IP地址分配、VIP地址+端口分配、VM和VM流量包过滤、加载负载均衡允许服务的流量;


6、部署FC GuestAgent

云架构系列之一-Azure云核心内核系统架构详解

  • Guest Agent部署:FC部署Guest Agent(后续会有专题分析FC的全套体系),可以看到Azure的Trust Boundary是通过虚拟机和物理节点,这里可以看到Hyper-V自身存在攻击面,另外Guest Agent和FC Host Agent也存在对应的攻击面;另外看到一些资料说Hyper-V的核心代码不到一万行都是经过形式化验证的;


Azure云平台工程化架构思路和落地实践
一、Azure底座基础设施工程化落地(DAL+HAL+CIM+WS-Man+OMI五件套)
1、Azure面临的复杂性
Azure云平台的构建来源于复杂的底层软硬件支撑,例如Azure会在各种软硬件制造商那里采购了各种设备和软件。包括数据中心硬件、刀片、负载均衡、PDU、交换机和路由器等,最关键的是这些设备来源不同厂商,而且这些设备在某些情况下通过使用不同的协议、方案和专有解决方案来进行管理。Azure Fabric Controller为了管理这些硬件和软件,屏蔽复杂性和简化设备管理,必须从架构层面设计一个系统来抽象解决这些复杂的问题。

2、Azure工程化解决方案
Azure工程化团队跟Windows工程团队紧密合作,跟Windows系统团队一起定义了对应的解决方案,那就是DAL(DataCenter Abstraction Layer)、HAL、CIM、WS-Man、OMI五件套(一句话总结OMI是DAL的开源实现,通过WS-Man的协议来实现CIM的标准,最终达到微软的核心的想要解决复杂生态管理硬件和软件的一致性、标准型、扩平台、扩操作系统的战略目的)。下面分别介绍一下,然后就开始非常深入的详细分析。

DAL(DataCenter Abstraction Layer):问题是Windows是世界流行的操作系统,操作系统需要跟世界上流行的厂商DELL、HP、Cisco等进行集成,管理这些硬件、操作系统、软件等非常复杂。解决方案为了降低供应商广泛的硬件、软件、操作系统管理复杂和提升编程效率、统一化进行了构建了DAL为Microsoft生态和内部的开发生态进行统一管理,构建了一层抽象层来屏蔽供应商的复杂,达到了外部和内部的研发统一生态,提升研发、生态、合作伙伴等的统一性、标准化工作。

CIM(Common Information Model):通用信息模型提供了主动控制和管理DAL提出和管理复杂的供应链的硬件和软件的手段。CIM针对硬件、网络、系统、应用和服务的管理的一致性定义。

WS-Man:WS-Man协议的目的是为各种类型的设备 (包括固件) 和操作系统的管理操作提供一致性和互操作性,通过WS-Man可管理计算机系统(例如:个人计算机、工作站、服务器、智能设备)的协议。其提供Web Services服务,以帮助计算机系统和基于网络的服务进行无缝的协作。其中WinRM(Windows远程管理)就是微软WS-Man的实现。

OMI:通过OMI接口,微软云操作系统Windows Server可以管理数据中心内的所有设备。其实就是DAL的一个最终的实现,通过OMI可以管理HP-UX、Sun Solaris、Red Hat Enterprise Linux、SUSE、IBM AIX、MacOS、Cisco等等,通过OMI自定义的MOF Schema来实现CIM通用信息模型的标准。

3、Microsoft DAL详细分析
Azure工程化团队为了应对复杂的、不断增长的数据中心(Azure数据中心需要管理来自设备制造商的不同类别的设备例如Cisco路由器、交换机、底层的硬件、BIOS等,另外随着Azure的工程化)环境所面临的管理挑战,需要易于使用的管理方法,促进端到端的管理操作。为了解决上述的这些问题,DAL(DataCenter Abstraction Layer)数据中心抽象层应运而生,DAL提供了一个一致性的开发者抽象层模型,以便Azure Fabric Controller、Windows、System Center和其他的系统、分布式操作系统、系统管理软件以及其他的管理系统通过DAL来管理底层各种供应商的广泛设备进行交互和互动,包括计算、存储、网络、操作系统、硬件或者其他设备等等。在DAL出现之前,数据中心的大多数设备都是通过使用各种厂商定义的协议和对应的管理工具来进行管理的。

云架构系列之一-Azure云核心内核系统架构详解

对于Azure系统管理员来说,通过Windows Powershell实现的CIM(https://docs.microsoft.com/en-us/powershell/module/cimcmdlets/?view=powershell-7.1)来实现的DAL层来进行管理,提供Azure一致性的数据中心基础设施管理平台。

笔者来分享一个案例,Azure云基础设施解决方案团队的某一个研发人员,目前正在开发一个云基础设施解决方案部署工具,这个工具用来管理所有的硬件。根据没有DAL之前,需要通过IMPI或SMASH来管理。这个研发想做的事情包括:设置电源状态(开或关)、改变启动顺序(持久化的改变和一次性的)、更新对应的固件、从BMC获取事件日志、提供一份硬件的相关清单。这里的问题是IMPI和SMASH有虽然是一套通用标准,但是它们都有非常复杂性的实现开发细节等,让Azure云基础设施团队来说增加了很多无形的成本。此时DAL的出现恰逢其时,通过DAL标准协议和通用的抽象层来屏蔽掉IMPI和SMASH对接的复杂性,来实现复杂的设备管理。另外一个好处就是管理Azure云基础设施的数据中心过度到了一个基于标准化的管理环境。另外除了系统、硬件管理,对于TOR交换机(参考《鸟哥谈云安全》第一篇讲到了Azure的网络架构),Azure云也实现了一套Windows PowerShell cmdlets来进行管理,包括Cisco、A10等可以在交换机中实现TOR CIM模式,通过WS-Man协议+CIM信息标准实现统一的交换机、负载均衡、安全等设备的复杂性管理。总结一下,通过采用DAL后大大提升Azure云的管理简单化,实现一致管理、基于标准化的管理体系。

4、Microsoft CIM详细分析
上面讲到了CIM的简单介绍,从DMTF的标准定义来看CIM标准包含了包括CIM_Application(应用管理)、CIM_Core、CIM_Database(数据库管理)、CIM_Device(设备管理)、CIM_Event(日志管理)、CIM_Network(网络管理)、CIM_Physical(物理设施管理)、CIM_System(系统管理)、CIM_User(用户管理)、CIM_Security(安全管理)等众多维度。下面举一个例子就好了,然后在看一下Windows的对应的CIM实现。

例如下面的CIM_System系统管理模块,这块也实现了30+的功能,包括本地文件系统、远程文件系统、文件服务、进程、操作系统等等内容。通过对应的定义的数据模型,来规范CIM系统管理的层次和调用的关系。另外说个题外话,漂亮国一直在定义各种标准,包括CVE、ATT&CK、CVSS、STIX等等标准,所以漂亮国很重视这块,也在大力发展各行各业的标准,从标准上掌握技术命脉的目的。

云架构系列之一-Azure云核心内核系统架构详解

再具体看一个Process进程的CIM的例子,首先创建了Job任务、任务调用BatchService批处理任务、任务产生了Service服务、服务最终执行了Process进程。整个流程大家清楚之后,我们就看2个点,Service服务执行Process流程,首先看一下Service服务的模型包括,另外Service服务模型调用了Process(模型包括CreationClassName:String名字格式字符型、Priority:unit32运行优先级格式是数字、ExecutionState:unit16进程执行状态)等。

云架构系列之一-Azure云核心内核系统架构详解

下面看一下Windows CIM的最终实现,Windows的标准实现名是以win32_开头的标准。Windows CIM实现了四个大的类别包括计算系统硬件类、操作系统类、性能计数器类和WMI服务管理类(详情:https://docs.microsoft.com/zh-cn/windows/win32/cimwin32prov/win32-provider)。


具体的我们只看一个操作系统的例子Win32_Process。首先看Win32_Process用来管理整个Windows的进程。第一步先看一下Windows是如何扩展CIM_Process的。从下面可以明显的看到,除了CIM_Process的模型外,扩展了不少的模型定义,包括ExecutablePath运行路径、内存相关一些管理,通过CIM的模型,Windows进行了对应的扩展。

[Dynamic, Provider("CIMWin32"), SupportsCreate, CreateBy("Create"), SupportsDelete, DeleteBy("DeleteInstance"), UUID("{8502C4DC-5FBB-11D2-AAC1-006008C78BC7}"), DisplayName("Processes"), AMENDMENT]class Win32_Process : CIM_Process{  string   CreationClassName;  string   Caption;  string   CommandLine;  datetime CreationDate;  string   CSCreationClassName;  string   CSName;  string   Description;  string   ExecutablePath;  uint16   ExecutionState;  string   Handle;  uint32   HandleCount;  datetime InstallDate;  uint64   KernelModeTime;  uint32   MaximumWorkingSetSize;  uint32   MinimumWorkingSetSize;  string   Name;  string   OSCreationClassName;  string   OSName;  uint64   OtherOperationCount;  uint64   OtherTransferCount;  uint32   PageFaults;  uint32   PageFileUsage;  uint32   ParentProcessId;  uint32   PeakPageFileUsage;  uint64   PeakVirtualSize;  uint32   PeakWorkingSetSize;  uint32   Priority = NULL;  uint64   PrivatePageCount;  uint32   ProcessId;  uint32   QuotaNonPagedPoolUsage;  uint32   QuotaPagedPoolUsage;  uint32   QuotaPeakNonPagedPoolUsage;  uint32   QuotaPeakPagedPoolUsage;  uint64   ReadOperationCount;  uint64   ReadTransferCount;  uint32   SessionId;  string   Status;  datetime TerminationDate;  uint32   ThreadCount;  uint64   UserModeTime;  uint64   VirtualSize;  string   WindowsVersion;  uint64   WorkingSetSize;  uint64   WriteOperationCount;  uint64   WriteTransferCount;};

有了定义之后,笔者带大家看一下如何执行的,Windows CIM通过WQL语言来进行查询的,后续讲解Azure的时候会详细讲解Azure云平台如何调用的。
strComputer = "."Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & strComputer & "rootcimv2")Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process")For Each objProcess in colProcessList Wscript.Echo "Process: " & objProcess.Name Wscript.Echo "Process ID: " & objProcess.ProcessID Wscript.Echo "Thread Count: " & objProcess.ThreadCount Wscript.Echo "Page File Size: " & objProcess.PageFileUsage Wscript.Echo "Page Faults: " & objProcess.PageFaults Wscript.Echo "Working Set Size: " & objProcess.WorkingSetSizeNext


5、Microsoft WS-Man详细分析
Windows远程管理Windows Remote Management(WinRM)就是通过WS-Man协议来进行远程管理的实现。该协议为Azure云管理服务器提供了非常方便的方式,通过WinRM在Azure云中进行部署、远程管理等东西。WS-Man采用了标准了SOAP协议来进行管理。


客户端执行WinRM管理:

$UserName = "AzureCloudUser"$serverpass = "P@ssw0rd"
$Password = ConvertTo-SecureString $serverpass -AsPlainText –Force$cred = New-Object System.Management.Automation.PSCredential($UserName,$Password)
invoke-command -ComputerName localhost -Credential $cred -ScriptBlock { ipconfig }


服务端接受WS-Man SOAP协议请求

<s:Envelope    xmlns:s="http://www.w3.org/2003/05/soap-envelope"   xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"   xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">   <s:Header>     <wsa:To>       http://localhost:80/wsman     </wsa:To>     <wsman:ResourceURI s:mustUnderstand="true">       http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd     </wsman:ResourceURI>     <wsa:ReplyTo>       <wsa:Address s:mustUnderstand="true">         http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous       </wsa:Address>     </wsa:ReplyTo>     <wsa:Action s:mustUnderstand="true">       http://schemas.xmlsoap.org/ws/2004/09/transfer/Create     </wsa:Action>     <wsman:MaxEnvelopeSize s:mustUnderstand="true">153600</wsman:MaxEnvelopeSize>     <wsa:MessageID>uuid:AF6A2E07-BA33-496E-8AFA-E77D241A2F2F</wsa:MessageID>     <wsman:Locale xml:lang="en-US" s:mustUnderstand="false" />     <wsman:OptionSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">       <wsman:Option Name="WINRS_NOPROFILE">TRUE</wsman:Option>       <wsman:Option Name="WINRS_CODEPAGE">437</wsman:Option>     </wsman:OptionSet>     <wsman:OperationTimeout>PT60.000S</wsman:OperationTimeout>   </s:Header>   <s:Body>     <rsp:Shell  xmlns:rsp="http://schemas.microsoft.com/wbem/wsman/1/windows/shell">       <rsp:Environment>         <rsp:Variable Name="test">1</rsp:Variable>       </rsp:Environment>       <rsp:WorkingDirectory>d:windows</rsp:WorkingDirectory>       <rsp:Lifetime>PT1000.000S</rsp:Lifetime>       <rsp:InputStreams>stdin</rsp:InputStreams>       <rsp:OutputStreams>stdout stderr</rsp:OutputStreams>     </rsp:Shell>       <CommandLine xmlns='http://schemas.microsoft.com/wbem/wsman/1/windows/shell'>        <Command>powershell</Command>        <Arguments>ifconfig</Arguments>      </CommandLine>   </s:Body> </s:Envelope>


6、Microsoft OMI详细分析

OMI其实简单点说就是DAL的一种实现,微软和OpenGroup组织一起定义OMI管理,大力发展基于标准的管理。微软与Arista和Cisco合作,把OMI开放到他们的交换机上,用来为Azure和云数据中心的统一标准化管理。实现这套标准之后,可以通过标准的工具来管理服务器上的BMC、Windows操作系统和运行OMI的Arista、Cisco的交换机。


其实OMI主要解决的问题就是如今的Azure和数据中心由一系列不同硬件和平台供应商提供的异构设备,需要不同的工具和管理流程来进行管理。而大型企业被迫编写自己的抽象层,或者被Cisco这种厂商锁定,严重限制灵活性。所以微软通过推动行业采用抽象层和标准化的工作来进行管理。


Azure Fabric Controller架构

在正式开始详细分析Azure Fabric Controller的技术细节之前,还是先了解下整个Azure数据中心的架构。

云架构系列之一-Azure云核心内核系统架构详解

Azure数据中心由非常的Region组成,Region通过AZ组成,AZ通过一个一个的Cluster集群、Cluster集群通过Node机架、Node机架通过交换机和服务器组成了庞大的Azure数据中心。


每一个Cluster集群都会通过Fabric Controller来进行管理,Fabric Controller的主要职责和Azure的服务生命周期管理、Azure虚拟机生命周期的管理、Azure数据中心物理服务器的监控状态管理、Azure云进行Scale-Out扩展的时候进行服务器的扩容管理等等、Fabric Controller会管理Azure硬件服务器的部署和使用,并且最终完成Azure服务部署和管理应用生命周期的核心云内核核心。


从底层设计来看Cluster集群上面还有一个Utility Fabric Controller(UFC),UFC是Fabric Controller的Leader,UFC会负责所有的Fabric Controller的管理例如会把服务器Node节点的信息通过XML传递给Fabric Controller,方便其管理资源。另外在Cluster集群分布式管理上还会有很多分布式状态例如etcd,会选举集群Leader,选取的Leader来传递对应的服务器配置信息,通过配置信息去通过Fabric Controller去进行管理。


Fabric Controller进行管理的话,是通过部署在每台Azure服务器上的HostAgent组件进行管理的。另外在Fabric Controller HostAgent管理的虚拟机上,安装GuestAgent,用来跟HostAgent进行通信。


Azure的云产品服务是通过*.cspkg(Cloud Service Package)以及*.cscfg(Cloud Service Configuration)来进行部署。


下面简单讲解一下Azure服务部署的文件内容的作用:

.cspkg:用来封装Azure云产品服务所有的文件,包括执行文件PE EXE和依赖的DLLs文件,如果有Web.config和App.config也会一起部署;

.csdef:用来定义Azure云产品服务所依赖的环境,包括使用的Role(虚拟机的角色)、网络服务、虚拟机的数量等信息;

.cscfg:用来定义Azure云产品服务所依赖的配置信息,包括对应的Storage Account、远程桌面RDP参数等;


截止到现在目前已经讲清楚整个Azure云平台的大的架构了,下面开始讲解一些细节实现。


Azure Fabric Controller详解
一、Fabric Controller Host Agent详解
1、安装脚本
整个Azure云的安装基本上都是脚本化进行安装的,工程化程度也是非常高的,后续如果有机会的可以可以分享一下Azure整个云平台的安装步骤。其中安装Azure Fabric Controller Host Agent的配置和脚本来详细讲解一下。
  • 设置Host Agent端口

Host Agent的端口是14200,主要后续用来做防火墙入的规则和开放HTTP的端口来使用;
Set-Variable -Name HostAgentPort -Option Constant -Value 14200

  • 设置操作系统防火墙

利用New-NetFirewallRule来创建14200端口的入方向规则,可以看到并没有做一些IP地址的限制等策略;

Set-Variable -Name HostAgentFirewallRuleName -Option Constant -Value "AzsHostAgent"Set-Variable -Name HostAgentFirewallRulePort -Option Constant -Value 14200Set-Variable -Name HostAgentFirewallDisplayName -Option Constant -Value "Allow inbound TCP traffic for AzsHostAgentNew-NetFirewallRule -Name $HostAgentFirewallRuleName -DisplayName $HostAgentFirewallDisplayName -Enabled True -Direction Inbound -Action Allow -Protocol TCP -LocalPort $HostAgentFirewallRulePort

  • 通过前面讲到的CIM协议来进行部署的账号的账号变更和新服务的创建。通过服务创建,设置自启动的Azure Fabric Controller Host Agent运行服务。

 New-Service -Name $ServiceName -DisplayName $DisplayName -BinaryPathName $ExePath -Description "This is the Host Agent Service" -StartupType Automatic $SvcWmi = Get-CimInstance -ClassName Win32_Service | Where-Object Name -eq $ServiceName $ret = Invoke-CimMethod -InputObject $SvcWmi -MethodName Change -Arguments @{StartName="$env:USERDOMAINazs-jea-comsa$";StartPassword=""}

2、Fabric Controller HostAgent开发框架
开放14200端口之后,背后的服务是基于Microsoft ASP.NET MVC框架进行开发。看到这里,笔者还是有话要说,Azure云确实在统一化方面做的非常领先,通过前面的阅读大家应该了解Azure在DAL、CIM、WS-Man等方面做的统一化,这里要提一嘴,Azure云产品的服务程序控制台也全部依靠Microsoft ASP.NET MVC框架开发的程序,非常的统一,另外Azure在云产品服务上也做了很多的设计,包括前端后端分离,RestFull API框架统一、底层研发框架统一、Json处理框架统一等等。后续有机会的话,一定要介绍Azure云产品的开发框架。

通过ASP.NET MVC框架的基础上,把对应的请求进行RestFull API操作,具体的可以看一下例子,下面就是针对虚拟机管理的一个APIController的定义。
using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Client.Models;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Client.Models.VMs;
[Route("host")][ApiController]public abstract class HostVirtualMachineController : ControllerBase{ [HttpGet("vms/{vmName}/powerState")] public abstract Task<ActionResult<VmPowerState>> GetVmPowerState(string vmName, bool noCache = true);
[HttpPut("vms/{vmName}")] public abstract Task<ActionResult> PutVirtualMachine(string vmName, VirtualMachine virtualMachine);
[HttpGet("vms/{vmName}")] public abstract Task<ActionResult<VirtualMachine>> GetVirtualMachine(string vmName);
[HttpDelete("vms/{vmName}")] public abstract Task<ActionResult> DeleteVirtualMachine(string vmName);
[HttpGet("vms/{vmName}/thumbnail/width/{widthPixels}/height/{heightPixels}")] public abstract Task<ActionResult<VmThumbnail>> GetVirtualMachineThumbnail(string vmName, ushort widthPixels, ushort heightPixels);
[HttpGet("vms/{vmName}/memorySettings")] public abstract Task<ActionResult<VirtualMachineMemorySettings>> GetVirtualMachineMemorySettings(string vmName);
[HttpPatch("vms/{vmName}/memorySettings")] public abstract Task<ActionResult> SetVirtualMachineMemorySettings(string vmName, VirtualMachineMemorySettings virtualMachineMemorySettings);
[HttpGet("vms/{vmName}/memoryData")] public abstract Task<ActionResult<VirtualMachineMemoryData>> GetVirtualMachineMemoryData(string vmName);
[HttpPut("vms/{vmName}/notes")] public abstract Task<ActionResult> SetVmNotes(string vmName, VmNotes notes);
[HttpGet("vms/{vmName}/smBios")] public abstract Task<ActionResult<VmSmBios>> GetVmSmBios(string vmName);
[HttpPut("vms/{vmName}/smBios")] public abstract Task<ActionResult> SetVmSmBios(string vmName, VmSmBios smBios);
[HttpPatch("vms/{vmName}/processorSettings")] public abstract Task<ActionResult> SetVirtualMachineProcessorSettings(string vmName, VirtualMachineProcessorSettings virtualMachineProcessorSettings);
[HttpGet("vms/{vmName}/processorSettings")] public abstract Task<ActionResult<VirtualMachineProcessorSettings>> GetVirtualMachineProcessorSettings(string vmName);
[HttpHead("vms/{vmName}")] public abstract Task<ActionResult> DoesVirtualMachineExist(string vmName);
[HttpGet("vms/{vmName}/generation")] public abstract Task<ActionResult<VmGeneration>> GetVmGeneration(string vmName);
[HttpGet("vms/{vmName}/hardwareProfile")] public abstract Task<ActionResult<VmHardwareProfile>> GetVmHardwareProfile(string vmName);
[HttpPost("vms/{vmName}")] public abstract Task<ActionResult> UpdateVmPowerState(string vmName, string action);
[HttpPost("vms/{vmName}/powerState")] public abstract Task<ActionResult<Job>> AsyncUpdateVmPowerState(string vmName, string action);}

3、Fabric Controller HostAgent安全鉴权
前面已经讲到了采用ASP.NET MVC的RestFull API的模式来进行管理,那读者肯定会好奇他到底有没有做鉴权。下面看一下对应的鉴权逻辑。其实也不是很复杂,所有的API全部通过X509Certificate2证书的格式来进行认证,聪明的读者肯定又会问了证书如何管理,它的证书放到内部的dSMS(内部Key Vault)密钥管理系统里面进行托管,保证调用方和被调用方的安全。
using System;using System.Diagnostics.CodeAnalysis;using System.Security.Claims;using System.Security.Cryptography.X509Certificates;using System.Threading.Tasks;using Microsoft.AspNetCore.Authentication.Certificate;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Controllers.Contract;
[ExcludeFromCodeCoverage]public class CertificateAuthenticationHandler : ICertificateAuthenticationHandler{ private readonly X509Certificate2 peerCertificate;
public CertificateAuthenticationHandler(X509Certificate2 peerCertificate) { this.peerCertificate = peerCertificate; }
public Task OnCertficateValidated(CertificateValidatedContext context) { if (IsValidCertificate(context.ClientCertificate)) { Claim[] claims = new Claim[2] { new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", context.ClientCertificate.Subject, "http://www.w3.org/2001/XMLSchema#string", context.Options.ClaimsIssuer), new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", context.ClientCertificate.Subject, "http://www.w3.org/2001/XMLSchema#string", context.Options.ClaimsIssuer) }; context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name)); context.Success(); return Task.CompletedTask; } throw new UnauthorizedAccessException($"The request is unauthorized because the client certificate thumbprint {context.ClientCertificate.Thumbprint} is not authorized"); }
private bool IsValidCertificate(X509Certificate2 clientCertificate) { return clientCertificate.Thumbprint == peerCertificate.Thumbprint; }}

4、虚拟机(VM)生命周期管理

通过前面的ASP.NET MVC APIController进入对应的处理逻辑。再详细讲解后台调用之前,先看一下Azure Fabric Controller针对虚拟机管理的生命周期包含哪些操作。包括电源管理(开机、关机)、虚拟机创建、虚拟机销毁、内存管理、内存设置、BIOS设置、CPU处理、CPU设置、硬件管理、热迁移、虚拟机硬盘、网络配置、虚拟路由器配置、网络安全组设置等等。


下面针对创建虚拟机这个过程来进行看一下Azure的虚拟机到底是如何创建的?第一步在Azure云产品控制台发起了创建的请求,通过层层调用发送到了Fabric Controller HostAgent 14200端口的API请求[HttpPut("vms/{vmName}")]来进行调用,通过跟踪Controller API的跟进,看到实际的虚拟机操作逻辑如下(是不是非常简单,简洁和具备高可读性):

using System;using System.Collections.Generic;using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Client.Models;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Contract;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Models;
public override async Task<ActionResult> PutVirtualMachine(string vmName, Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Client.Models.VirtualMachine virtualMachine){ if (!vmName.Equals(virtualMachine.Name, StringComparison.InvariantCultureIgnoreCase)) { return BadRequest($"Virtual Machine name does not match the model. Uri: {vmName} Model: {virtualMachine.Name}"); } Func<Task<ActionResult>> createVm = async delegate { try { await hostFabricManager.GetVirtualMachine(AzureVmId.Parse(vmName)); return Ok(); } catch (FabricVmNotFoundException) { } Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Models.VirtualMachine coreModel = converter.Convert(virtualMachine); await hostFabricManager.CreateVirtualMachine(coreModel); return Ok(); }; Dictionary<string, int> exceptionMapping = new Dictionary<string, int> { ["FabricVirtualMachineNotFound"] = 455 }; return await errorHandler.HandleFabricExceptions(createVm, exceptionMapping);}


继续跟进关键函数hostFabricManager

await hostFabricManager.CreateVirtualMachine(coreModel);


往下继续调用,发现使用hyperVWmiInvoker这个函数,继续跟进。这里要提一下,从Portal.azure.com控制台来创建虚拟机开始,经过层层的调用,最终还是在Windows Server上利用Hyper-V进行了虚拟机的创建流程。

using System.Threading.Tasks;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Models;
public async Task CreateVirtualMachine(VirtualMachine virtualMachine){ string path = await fileSharePathConverter.ConvertPathOnCluster(virtualMachine.Path); await hyperVWmiInvoker.CreateVirtualMachine(virtualMachine.AzureVmId, path);}


继续跟可以最终调用Windows 实现CIM模块对Hyper-V进行了调用。CIM的Hyper-V模块是CimInstance("Msvm_VirtualSystemSettingData", "root\virtualization\v2");


root\virtualization\v2的含义是Hyper-V通过WMI CIM模块提供的底层Namespace,再这个Namespace下首先调用了Msvm_VirtualSystemSettingData来进行配置操作,然后调用"DefineSystem"(https://docs.microsoft.com/en-us/windows/win32/hyperv_v2/definesystem-msvm-virtualsystemmanagementservice)最终创建了对应的虚拟机,完成整个虚拟机的操作工作。

using System;using System.Threading.Tasks;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Contract.Exceptions;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Models;using Microsoft.AzureStack.Fabric.HostAgent.HostAgent.Core.Source.Trace;using Microsoft.Management.Infrastructure;using Microsoft.Management.Infrastructure.Generic;using Microsoft.Management.Infrastructure.Serialization;
public async Task CreateVirtualMachine(AzureVmId azureVmId, string path){ using CimInstance vssdCimInstance = new CimInstance("Msvm_VirtualSystemSettingData", "root\virtualization\v2"); vssdCimInstance.CimInstanceProperties.Add(CimProperty.Create("ElementName", azureVmId.ToString(), CimType.String, CimFlags.Required)); vssdCimInstance.CimInstanceProperties.Add(CimProperty.Create("ConfigurationDataRoot", path, CimType.String, CimFlags.None)); vssdCimInstance.CimInstanceProperties.Add(CimProperty.Create("AutomaticShutdownAction", (ushort)4, CimType.UInt16, CimFlags.None)); byte[] serializedVssdCimInstance = cimSerializer.Serialize(vssdCimInstance, InstanceSerializationOptions.None); using CimInstance vmmsCimInstance = await virtualSystemManagementServiceProvider.GetVmmsCimInstance(); using CimMethodParametersCollection parameters = new CimMethodParametersCollection { CimMethodParameter.Create("SystemSettings", unicodeEncoding.GetString(serializedVssdCimInstance), CimType.String, CimFlags.In) }; try { CimInstance resultingSystem = (CimInstance)(await cimMethodAsyncOperationPoller.InvokeMethodOnCimInstanceAndWaitForCompletion("root\virtualization\v2", "DefineSystem", parameters, vmmsCimInstance, string.Format(Literals.CreatingVirtualMachine, azureVmId.ToString(), path))).OutParameters["ResultingSystem"].Value; using (CimInstance kvpSettings = await GetSingleKvpExchangeComponentSettingsData(azureVmId)) { if (kvpSettings != null) { HostAgentLogger.DeletePreExistingDuplicateVms(azureVmId); await TryCleanupVm(vmmsCimInstance, azureVmId); throw new KvpSettingsForFabricVmAlreadyExistException(azureVmId); } await CreateKvpExchangeDataItem(resultingSystem, azureVmId); } Action<CimKeyedCollection<CimProperty>> updateAction = delegate(CimKeyedCollection<CimProperty> settings) { settings["ElementName"].Value = "SCSI Controller"; settings["VirtualSystemIdentifiers"].Value = new string[1] { "{f8b3781b-1e82-4818-a1c3-63d806ec15bb}" }; }; HypervVmId hypervVmId = HypervVmId.Parse(resultingSystem.CimInstanceProperties["Name"].Value.ToString()); await vmResourceHandler.AddResourceToVm(hypervVmId, "Microsoft:Hyper-V:Synthetic SCSI Controller", "Msvm_ResourceAllocationSettingData", updateAction); } catch (KvpSettingsForFabricVmAlreadyExistException e2) { HostAgentLogger.KvpSettingsForFabricVmAlreadyExist(azureVmId, e2); } catch (Exception e) { HostAgentLogger.AttemptVmDeletionAfterVmCreationFailure(azureVmId, e); await TryCleanupVm(vmmsCimInstance, azureVmId); throw; }}


这里还是要简单介绍一下DefineSystem的定义,可以看到还是调用CIM的标准的数据模型,CIM_VirtualSystemSettingData、CIM_ComputerSystem、CIM_ConcreateJob等模型的,对应上笔者之前说的CIM模型。

uint32 DefineSystem(  [in]  string                           SystemSettings,  [in]  string                           ResourceSettings[],  [in]  CIM_VirtualSystemSettingData REF ReferenceConfiguration,  [out] CIM_ComputerSystem           REF ResultingSystem,  [out] CIM_ConcreteJob              REF Job)


其他虚拟机管理的流程类似,就不做过多的介绍了。读者可以参考这里的API来看整个Azure虚拟机支持的各种资源操作。(https://docs.microsoft.com/en-us/rest/api/compute/virtual-machines)


备注:这里有个小的备注,Azure虚拟机的生命周期管理中标识虚拟机的唯一标识是分成AzureVMID和HyperVID两种的,这里会有点小误区。其实AzureVMID就是Azure云平台来标识虚拟机的,到物理机上通过HyperVID来标识,这里面需要维护两个ID标识的关系。


5、物理机生命周期管理

介绍完虚拟机的生命周期管理,下面看一下物理机的生命周期管理。例如下面的查询物理机的内存状态,通过之前讲到的CIM的Windows实现来查询可用的内存,如内存不足可以触发对应的虚拟机操作,关于物理机的其他操作大概都是类似的动作,不再赘述:

#查询物理机可用的内存SELECT AvailableMemory FROM Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryBalancer#查询物理机有多少对应的虚拟机SELECT * FROM Msvm_ComputerSystem WHERE Description = 'Microsoft Virtual Machine'


6、Azure云产品服务管理

Azure云产品服务管理较复杂,需打通DevOps的相关流程,再部署侧也比较复杂,前面讲到了,需要部署对应的cspkg、cscfg等文件,后续会再对应的后续文章中详细讲解。


Azure Fabric Controller漏洞(翻译)

毕竟是讲解云安全的公众号,不讲解一些安全的内容肯定不满足各位读者的要求,下面针对近期出现的CVE-2021-27075漏洞(https://www.intezer.com/blog/cloud-security/cve-2021-27075-microsoft-azure-vulnerability-allows-privilege-escalation-and-leak-of-data/)。


CVE-2021-27075漏洞会让没有特权的用户泄露任何Azure虚拟机扩展的私人数据。VMAccess扩展是Azure官方为协助系统管理员而设计的扩展,与之相配,国外研究者将展示如何利用这个漏洞实现权限升级,并可能实现横向移动。 


对应的POC:

云架构系列之一-Azure云核心内核系统架构详解

Azure VM为开发者和管理员提供了一个集成的插件系统,以便在他们的机器上安装额外的组件。第一方(如微软Azure诊断程序和微软Azure网络观察者)和第三方应用程序(如Datadog代理)都是通过这个机制提供的(例外笔者说一下第二篇的Azure的威胁分析Extension模块也是这样获取的^_^)。


为了管理扩展的安装并保持更新,系统上安装了Microsoft Azure Guest Agent。这个组件是开源的,托管在GitHub上。这个代理,连同Azure扩展,安装在/var/lib/waagent。这个目录对于非root用户来说是无法访问的,因为它包含与扩展相关的秘密漏洞。


扩展程序被安装在这个目录下对应的子目录中,例如,/var/lib/waagent/Microsoft.Azure.NetworkWatcher.NetworkWatcherAgentLinux-1.4.1587.1 许多共享配置被布置在根扩展目录/var/lib/waagent。

云架构系列之一-Azure云核心内核系统架构详解


当一个扩展被添加到虚拟机中时,扩展的配置文件会在Azure虚拟机管理器(也称为Fabric Controller)中进行后台通信。WAAgent不断地轮询Fabric Controller的这个文件,一旦更新,扩展就被下载和部署。在微软Azure云中,WAAgent与 "Wire Server "进行通信,这是一个属于Fabric Controller的HTTP服务。

WAAgent通过访问一个特殊的IP地址与织物控制器进行通信。168.63.129.16.通过一些测试,国外白帽子发现这个端点与169.254.169.254相同,也就是大家熟知的Azure实例元数据服务IP地址。


WAAgent通过解析'GoalState'来接收扩展配置URL。 

云架构系列之一-Azure云核心内核系统架构详解


目标状态端点请求,HTTP响应如下:

云架构系列之一-Azure云核心内核系统架构详解


GoalState包含Wire Server可用的所有相关配置的URL。使用GoalState,我们可以自己查询ExtensionsConfig文件。 

云架构系列之一-Azure云核心内核系统架构详解


ExtensionsConfig端点请求。下面是一个关于LinuxDiagnostic扩展配置的例子。 

云架构系列之一-Azure云核心内核系统架构详解


ExtensionsConfig端点响应protectedSettings字段保存敏感的扩展配置,如私钥,并有额外的加密方案保护。protectedSettingsCertThumbprint字段持有用于解密protectedSettings的密钥的文件名。这个密钥存储在 /var/lib/waagent/F54265F38F8D16C35C0E1FD3190882831A6C4384.prv,其证书存储在/var/lib/waagent/F54265F38F8D16C35C0E1FD3190882831A6C4384.crt。


在这个部署中,使用了证书端点。在对WAAgent与Wire Server的通信进行逆向工程后,国外白帽子发现证书端点需要一个通信证书,用于提供F542...扩展密钥。 

云架构系列之一-Azure云核心内核系统架构详解


证书端点请求,服务器返回一个加密形式的扩展密钥,可以通过传输证书的私钥进行解密。 

云架构系列之一-Azure云核心内核系统架构详解


漏洞#1:证书端点没有验证传输证书

攻击者可以创建自己的传输私钥和其相应的传输证书。使用证书端点,攻击者提供他们自己的传输证书,并从对应的服务器接收加密形式的密钥(在我们的例子中,这是F54265F38F8D16C35C0E1FD3190882831A6C4384密钥)。

最后,加密的密钥通过传输密钥被解密,攻击者可以继续解密被保护的设置。  

云架构系列之一-Azure云核心内核系统架构详解

云架构系列之一-Azure云核心内核系统架构详解


在以根用户开发PoC后,它在非特权用户下无法工作。看来,服务器并没有把指向168.63.129.16的Wire Server终端的数据包发送出去。这是因为有一条iptables规则,它把不是来自用户ID 0(root)的数据包丢弃到端点。 

云架构系列之一-Azure云核心内核系统架构详解


漏洞二:绕过服务器非特权访问防御

如前所述,国外白帽子发现164.254.164.254与168.63.129.16是同一个机器。我们用164.254.164.254替换了对168.63.129.16的每个请求,这使得国外白帽子可以在没有特权用户的情况下与Wire Server进行通信。


此外,这种iptables防御并不适用于在Docker容器中运行的进程(甚至当PoC作为非特权用户运行时),允许容器通过Wire Server泄露其主机信息。这个问题也被MSRC修复了。


结合缺陷

利用这两个缺陷,无权的用户可以泄露任何Azure VM扩展的私人设置。当与处理敏感数据的扩展配对时,这尤其危险。


一个特别严重的例子是VMAccess扩展,这是微软Azure的官方扩展,用于在受控机器上方便地更改密码。Guardicore以前记录过,VMAccess即使在修改完用户的密码,不再需要在磁盘上保留密码,也会在protectedSettings字段中持续保留密码。


结合国外白帽子发现的漏洞,攻击者可以通过泄露VMAccess管理密码将自己提升为更高权限的用户。此外,如果VMAccess密码与其他Azure虚拟机共享(通常是这样),攻击者可以在系统中进行横向移动。

云架构系列之一-Azure云核心内核系统架构详解


最终的POC(导致物理机的密码泄露,通过普通用户达到提权):

云架构系列之一-Azure云核心内核系统架构详解

 

总结

本文针对Azure的云核心内核系统架构进行了详细的讲解,读者肯定会有行云流水般的感觉,因为整个分析的流程都是从顶层架构层层分解到最终实现的。在分析的将近1年多时间内(文章写了不到8个小时),学习到了非常多的Azure云的设计思想。包括统一和屏蔽Azure底层硬件、软件、操作系统复杂性的DAL以及通过WS-Man协议结合CIM来进行Azure整个服务器内部管理的体系,还有Azure Fabric Controller的云核心内核的详细分析。另外再总结一下,第一条线从Azure机器上架->部署Cluster->Node机架->Fabric Controller进行部署服务->构成机房->构成AZ->构成Region->构成Azure云的角度进行了讲解。第二条线是从Azure云平台Portal.azure.com申请账号部署虚拟机->Azure Fabric Controller调用->Hyper-V WMI进行调用->生成虚拟机的全套流程。第三条线就是Azure机器管理和对应的服务部署流程进行了详细讲解。第四条线是对应的漏洞。

过程中遇到了非常多的困难,感谢腾讯云@killer提供高配服务器进行研究、感谢IT小圈子作者Stan的精彩文章让我对Azure的架构有了顶层的认识、感谢某金融客户经常问我一些云的相关问题,让我对Azure的实现有了一些了解、感谢奇安信的"DadayKuan"同学一起愉快的交流,还有很多同学的鼓励才能写下去,另外还有一些同学也非常感谢不再一一列举。行文过程中难免有一些错误和不足,请联系微信@ThreatSource进行沟通交流、指正和好的建议。再次感谢各位读者的耐心阅读!!!


下篇见!!!


原文始发于微信公众号(鸟哥谈云安全):云架构系列之一-Azure云核心内核系统架构详解

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月2日18:43:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   云架构系列之一-Azure云核心内核系统架构详解http://cn-sec.com/archives/864894.html

发表评论

匿名网友 填写信息