Dapr 安全性之访问控制策略

    安全是 Dapr 的基础,本文我们将来说明在分布式应用中使用 Dapr 时的安全特性和能力,主要可以分为以下几个方面。

            

            与服务调用和pub/sub APIs 的安全通信。        

                

            组件上的安全策略并通过配置进行应用。        

                

            运维操作安全实践。        

                

            状态安全,专注于静态的数据。        

    

    Dapr 通过服务调用 API 提供端到端的安全性,能够使用 Dapr 对应用程序进行身份验证并设置端点访问策略。

    安全通信

    服务调用范围访问策略

    跨命名空间的服务调用

    Dapr 应用程序可以被限定在特定的命名空间,以实现部署和安全,当然我们仍然可以在部署到不同命名空间的服务之间进行调用。默认情况下,服务调用支持通过简单地引用应用 ID (比如 nodeapp) 来调用同一命名空间内的服务:

                                                                                
                        localhost:3500/v1.0/invoke/nodeapp/method/neworder                                                                                    

                                    1.                                

                            
                                        

    服务调用还支持跨命名空间的调用,在所有受支持的托管平台上,Dapr 应用程序 ID 符合包含目标命名空间的有效 FQDN 格式,可以同时指定:

            

            应用 ID (如nodeapp)。        

                

            应用程序运行的命名空间(production)。        

    

    比如在 production 命名空间中的 nodeapp 应用上调用 neworder 方法,则可以使用下面的方式:

                                                                                
                        localhost:3500/v1.0/invoke/nodeapp.production/method/neworder                                                                                    

                                    1.                                

                            
                                        

    当使用服务调用在命名空间中调用应用程序时,我们可以使用命名空间对其进行限定,特别在 Kubernetes 集群中的跨命名空间调用是非常有用的。

    为服务调用应用访问控制列表配置

    访问控制策略在配置文件中被指定,并被应用于被调用应用程序的 Dapr sidecar,对被调用应用程序的访问是基于匹配的策略动作,你可以为所有调用应用程序提供一个默认的全局动作,如果没有指定访问控制策略,默认行为是允许所有调用应用程序访问被调用的应用程序。

    在具体学习访问控制策略配置之前,我们需要先了解两个概念:

            

            TrustDomain - “信任域”是管理信任关系的逻辑组。每个应用程序都分配有一个信任域,可以在访问控制列表策略规范中指定。如果未定义策略规范或指定了空的信任域,则使用默认值 public,该信任域用于在 TLS 证书中生成应用程序的身份。        

                

            App Identity - Dapr 请求 sentry 服务为所有应用程序生成一个 SPIFFE id,这个 id 附加在 TLS 证书中。SPIFFE id 的格式为:spiffe:///ns//,对于匹配策略,调用应用的信任域、命名空间和应用 ID 值从调用应用的 TLS 证书中的 SPIFFE id 中提取,这些值与策略规范中指定的信任域、命名空间和应用 ID 值相匹配。如果这三个都匹配,则更具体的策略将进一步匹配。        

    

    访问控制策略会遵循如下所示的一些规则:

            

            如果未指定访问策略,则默认行为是允许所有应用访问被调用应用上的所有方法        

                

            如果未指定全局默认操作且未定义应用程序特定策略,则将空访问策略视为未指定访问策略,并且默认行为是允许所有应用程序访问被调用应用程序上的所有方法        

                

            如果未指定全局默认操作,但已定义了一些特定于应用程序的策略,则会采用更安全的选项,即假设全局默认操作拒绝访问被调用应用程序上的所有方法        

                

            如果定义了访问策略并且无法验证传入的应用程序凭据,则全局默认操作将生效        

                

            如果传入应用的信任域或命名空间与应用策略中指定的值不匹配,则应用策略将被忽略并且全局默认操作生效        

    

    下面是一些使用访问控制列表进行服务调用的示例场景。

    场景 1:拒绝所有应用程序的访问,除非 trustDomain = public、namespace = default、appId = app1,使用如下所示的配置,允许所有 appId = app1 的调用方法,并拒绝来自其他应用程序的所有其他调用请求。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: denytrustDomain: "public"policies:      -appId: app1defaultAction: allowtrustDomain: "public"namespace: "default"                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                            
                                        

    场景 2:拒绝访问除 trustDomain = public、namespace = default、appId = app1、operation = op1 之外的所有应用程序,使用此配置仅允许来自 appId = app1 的方法 op1,并且拒绝来自所有其他应用程序的所有其他方法请求,包括 app1 上的其他方法。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: denytrustDomain: "public"policies:      -appId: app1defaultAction: denytrustDomain: "public"namespace: "default"operations:          -name: /op1httpVerb: ["*"]            action: allow                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                            
                                        

    场景 3:拒绝对所有应用程序的访问,除非 HTTP 的特定 verb 和 GRPC 的操作匹配,使用如下所示的配置,仅允许以下场景访问,并且来自所有其他应用程序的所有其他方法请求(包括 app1 或 app2 上的其他方法)都会被拒绝。

            

            trustDomain = public、namespace = default、appID = app1、operation = op1、http verb = POST/PUT。        

                

            trustDomain = “myDomain”、namespace = “ns1”、appID = app2、operation = op2 并且应用程序协议是 GRPC,仅允许来自appId = app1 的方法 op1 上的 POST/PUT 请求以及来自所有其他应用程序的所有其他方法请求,包括 app1 上的其他方法,被拒绝。        

                                                                                    
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: denytrustDomain: "public"policies:      -appId: app1defaultAction: denytrustDomain: "public"namespace: "default"operations:          -name: /op1httpVerb: ["POST", "PUT"]            action: allow-appId: app2defaultAction: denytrustDomain: "myDomain"namespace: "ns1"operations:          -name: /op2action: allow                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                                                             

                                    18.                                

                                                             

                                    19.                                

                                                             

                                    20.                                

                                                             

                                    21.                                

                                                             

                                    22.                                

                                                             

                                    23.                                

                                                             

                                    24.                                

                            
                                        

    场景 4:允许访问除 trustDomain = public、namespace = default、appId = app1、operation = /op1/* 所有 http verb 之外的所有方法。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: allowtrustDomain: "public"policies:      -appId: app1defaultAction: allowtrustDomain: "public"namespace: "default"operations:          -name: /op1/*httpVerb: ["*"]action: deny                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                            
                                        

    场景 5:允许访问 trustDomain = public、namespace = ns1、appId = app1 的所有方法并拒绝访问 trustDomain = public、namespace = ns2、appId = app1 的所有方法,此场景展示了如何指定具有相同应用 ID 但属于不同命名空间的应用。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: allowtrustDomain: "public"policies:      -appId: app1defaultAction: allowtrustDomain: "public"namespace: "ns1"-appId: app1defaultAction: denytrustDomain: "public"namespace: "ns2"                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                            
                                        

    场景 6:允许访问除 trustDomain = public、namespace = default、appId = app1、operation = /op1/**/a、所有 http 动词之外的所有方法。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: appconfigspec:  accessControl:    defaultAction: allowtrustDomain: "public"policies:      -appId: app1defaultAction: allowtrustDomain: "public"namespace: "default"operations:          -name: /op1/**/ahttpVerb: ["*"]            action: deny                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                            
                                        

    下面我们通过一个具体的示例来展示下访问控制策略的使用,同样还是使用 quickstarts 示例中的 hello-world 进行说明。

                                                                                
                        gitclone [-b] https://github.com/dapr/quickstarts.gitcdquickstarts/tutorials/hello-world/node                                                                                    

                                    1.                                

                                                             

                                    2.                                

                            
                                        

    hello world

    该示例应用中包含一个 python 应用去调用一个 node.js 应用程序,访问控制列表依靠 Dapr Sentry 服务来生成带有 SPIFFE id 的 TLS 证书进行认证,这意味着 Sentry 服务必须在本地运行或部署到你的托管环境,比如 Kubernetes 集群。

    下面的 nodeappconfig 例子显示了如何拒绝来自 pythonapp 的 neworder 方法的访问,其中 pythonapp 是在 myDomain 信任域和 default 命名空间中,nodeapp 在 public 公共信任域中。

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: nodeappconfigspec:  tracing:    samplingRate: "1"accessControl:    defaultAction: allowtrustDomain: "public"policies:      -appId: pythonappdefaultAction: allowtrustDomain: "myDomain"namespace: "default"operations:          -name: /neworderhttpVerb: ["POST"]            action: deny                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                                                             

                                    17.                                

                                                             

                                    18.                                

                                                             

                                    19.                                

                            
                                                                                                                        
                        apiVersion: dapr.io/v1alpha1kind: Configurationmetadata:  name: pythonappconfigspec:  tracing:    samplingRate: "1"accessControl:    defaultAction: allowtrustDomain: "myDomain"                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                            
                                        

    接下来我们先在本地自拓管模式下来使用启用访问策略配置,首先需要在启用 mTLS 的情况下在本地运行 Sentry 服务,我们可以直接在 https://github.com/dapr/dapr/releases 页面下载对应的 sentry 二进制文件,比如我们这里是 Mac M1,则可以使用下面的命令直接下载:

                                                                                
                        $wgethttps://github.com/dapr/dapr/releases/download/v1.8.4/sentry_darwin_arm64.tar.gz$tar-xvfsentry_darwin_arm64.tar.gz                                                                                    

                                    1.                                

                                                             

                                    2.                                

                            
                                        

    然后为 Sentry 服务创建一个目录以创建自签名根证书:

                                                                                
                        $mkdir-p$HOME/.dapr/certs                                                                                    

                                    1.                                

                            
                                        

    使用以下命令在本地运行 Sentry 服务:

                                                                                
                        $ ./sentry--issuer-credentials$HOME/.dapr/certs--trust-domaincluster.localINFO[0000] startingsentrycertificateauthority--version1.8.4--commit18575823c74318c811d6cd6f57ffac76d5debe93instance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4INFO[0000] configuration: [port]: 50001, [castore]: default, [allowedclockskew]: 15m0s, [workloadcertttl]: 24h0m0sinstance=MBP2022.localscope=dapr.sentry.configtype=logver=1.8.4WARN[0000] loadingdefaultconfig. couldn't find config name: daprsystem: stat daprsystem: no such file or directory  instance=MBP2022.local scope=dapr.sentry type=log ver=1.8.4INFO[0000] startingwatchonfilesystemdirectory: /Users/cnych/.dapr/certsinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4INFO[0000] certificateauthorityloadedinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4INFO[0000] rootandissuercertsnotfound: generatingselfsignedCAinstance=MBP2022.localscope=dapr.sentry.catype=logver=1.8.4# ......INFO[0000] sentrycertificateauthorityisrunning, protectingya'll  instance=MBP2022.local scope=dapr.sentry type=log ver=1.8.4                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                            
                                        

    运行成功后 Sentry 服务将在指定目录中创建根证书,可以通过如下所示的命令来配置环境变量指定相关证书路径:

                                                                                
                        exportDAPR_TRUST_ANCHORS=`cat$HOME/.dapr/certs/ca.crt`exportDAPR_CERT_CHAIN=`cat$HOME/.dapr/certs/issuer.crt`exportDAPR_CERT_KEY=`cat$HOME/.dapr/certs/issuer.key`exportNAMESPACE=default                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                            
                                        

    然后我们就可以运行 daprd 为启用了 mTLS 的 node.js 应用启动 Dapr sidecar,并引用本地的 Sentry 服务:

                                                                                
                        daprd --app-id nodeapp --dapr-grpc-port 50002 -dapr-http-port 3501 -metrics-port 9091 --log-level debug --app-port 3000 --enable-mtls --sentry-address localhost:50001 --config nodeappconfig.yaml                                                                                    

                                    1.                                

                            
                                        

    上面的命令我们通过 --enable-mtls 启用了 mTLS,通过 --config 指定了上面的 nodeappconfig.yaml 这个配置文件。

    然后启动 node.js 应用:

                                                                                
                        $cdnode&&yarn$nodeapp.jsNodeApplisteningonport3000!                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                            
                                        

    同样的方式在另外的终端中设置环境变量:

                                                                                
                        exportDAPR_TRUST_ANCHORS=`cat$HOME/.dapr/certs/ca.crt`exportDAPR_CERT_CHAIN=`cat$HOME/.dapr/certs/issuer.crt`exportDAPR_CERT_KEY=`cat$HOME/.dapr/certs/issuer.key`exportNAMESPACE=default                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                            
                                        

    然后运行 daprd 为启用了 mTLS 的 python 应用启动 Dapr sidecar,并引用本地的 Sentry 服务:

                                                                                
                        daprd--app-idpythonapp--dapr-grpc-port50003--metrics-port9092--log-leveldebug--enable-mtls--sentry-addresslocalhost:50001--configpythonappconfig.yaml                                                                                    

                                    1.                                

                            
                                        

    在重新开一个终端直接启动 Python 应用即可:

                                                                                
                        $cdpython&&pip3install-rrequirements.txt$python3app.pyHTTP403=> {"errorCode":"ERR_DIRECT_INVOKE","message":"fail to invoke, id: nodeapp, err: rpc error: code = PermissionDenied desc = access control policy has denied access to appid: pythonapp operation: neworder verb: POST"}HTTP403=> {"errorCode":"ERR_DIRECT_INVOKE","message":"fail to invoke, id: nodeapp, err: rpc error: code = PermissionDenied desc = access control policy has denied access to appid: pythonapp operation: neworder verb: POST"}                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                            
                                        

    由于 nodeappconfig 文件中我们配置了对 /neworder 接口的 POST 拒绝操作,所以应该会在 python 应用程序命令提示符中看到对 node.js 应用程序的调用失败,如果我们将上面的 nodeappconfig 配置中的 action: deny 修改为 action: allow 并重新运行应用程序,然后我们应该会看到此调用成功。

    对于 Kubernetes 模式则更简单,只需要创建上述配置文件 nodeappconfig.yaml 和 pythonappconfig.yaml 并将其应用于 Kubernetes 集群,然后在应用的注解中添加 dapr.io/config: "pythonappconfig" 来指定配置即可开启服务访问控制。

                                                                                
                        annotations:  dapr.io/enabled: "true"dapr.io/app-id: "pythonapp"dapr.io/config: "pythonappconfig"                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                            
                                        

    Pub/sub 主题范围访问策略

    对于 Pub/sub 组件,你可以限制允许哪些主题类型和应用程序发布和订阅特定主题。

    命名空间或组件范围可用于限制组件对特定应用程序的访问,这些添加到组件的应用程序范围仅限制具有特定 ID 的应用程序能够使用该组件。如下所示显示了如何将两个启用 Dapr 的应用程序(应用程序 ID 为 app1 和 app2)授予名为 statestore 的 Redis 组件,该组件本身位于 production 命名空间中:

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Componentmetadata:  name: statestorenamespace: productionspec:  type: state.redisversion: v1metadata:    -name: redisHostvalue: redis-master:6379scopes:  -app1-app2                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                            
                                        

    除了这个通用组件的 scopes 范围之外,发布/订阅组件还可以限制以下内容:

            

            可以使用哪些主题(发布或订阅)。        

                

            允许哪些应用发布到特定主题。        

                

            允许哪些应用订阅特定主题。        

    

    这被称为发布/订阅主题范围。我们可以为每个发布/订阅组件定义发布/订阅范围,比如你可能有一个名为 pubsub 的 pub/sub 组件,它具有一组范围,另一个 pubsub2 具有另外不同的范围。

    示例 1:主题访问范围。如果你的主题包含敏感信息并且仅允许你的应用程序的子集发布或订阅这些信息,那么限制哪些应用程序可以发布/订阅主题可能会很有用。如下以下是三个应用程序和三个主题的示例:

                                                                                
                        apiVersion: dapr.io/v1alpha1kind: Componentmetadata:  name: pubsubspec:  type: pubsub.redisversion: v1metadata:    -name: redisHostvalue: "localhost:6379"-name: redisPasswordvalue: ""-name: publishingScopesvalue: "app1=topic1;app2=topic2,topic3;app3="-name: subscriptionScopesvalue: "app2=;app3=topic1"                                                                                    

                                    1.                                

                                                             

                                    2.                                

                                                             

                                    3.                                

                                                             

                                    4.                                

                                                             

                                    5.                                

                                                             

                                    6.                                

                                                             

                                    7.                                

                                                             

                                    8.                                

                                                             

                                    9.                                

                                                             

                                    10.                                

                                                             

                                    11.                                

                                                             

                                    12.                                

                                                             

                                    13.                                

                                                             

                                    14.                                

                                                             

                                    15.                                

                                                             

                                    16.                                

                            
                                        

    这里我们设置了 publishingScopes 和 subscriptionScopes 两个属性,分别用于配置发布范围和订阅范围。要拒绝应用发布到任何主题,请将主题列表留空,比如我们这里配置的 app1=topic1;app2=topic2,topic3;app3=,其中的 app3= 就表示该应用不允许发布到任何主题上去。

    根据我们的配置下表显示了允许哪些应用程序发布到主题中:

                                                                                

                    
                

国内免备案VPS301跳转服务器国内免备案服务器域名被墙跳转301,绕过信息安全中心不放违反法律法规内容!(北京免备案 镇江免备案 江苏免备案 辽宁免备案vps 山东联通免备案
 
在线咨询