安全是 Dapr 的基礎(chǔ),本文我們將來(lái)說(shuō)明在分布式應(yīng)用中使用 Dapr 時(shí)的安全特性和能力,主要可以分為以下幾個(gè)方面。
與服務(wù)調(diào)用和 pub/sub APIs 的安全通信。
組件上的安全策略并通過(guò)配置進(jìn)行應(yīng)用。
運(yùn)維操作安全實(shí)踐。
狀態(tài)安全,專(zhuān)注于靜態(tài)的數(shù)據(jù)。
Dapr 通過(guò)服務(wù)調(diào)用 API 提供端到端的安全性,能夠使用 Dapr 對(duì)應(yīng)用程序進(jìn)行身份驗(yàn)證并設(shè)置端點(diǎn)訪(fǎng)問(wèn)策略。
安全通信
服務(wù)調(diào)用范圍訪(fǎng)問(wèn)策略
跨命名空間的服務(wù)調(diào)用
Dapr 應(yīng)用程序可以被限定在特定的命名空間,以實(shí)現(xiàn)部署和安全,當(dāng)然我們?nèi)匀豢梢栽诓渴鸬讲煌臻g的服務(wù)之間進(jìn)行調(diào)用。默認(rèn)情況下,服務(wù)調(diào)用支持通過(guò)簡(jiǎn)單地引用應(yīng)用 ID (比如 nodeapp) 來(lái)調(diào)用同一命名空間內(nèi)的服務(wù):
localhost:3500/v1.0/invoke/nodeapp/method/neworder
服務(wù)調(diào)用還支持跨命名空間的調(diào)用,在所有受支持的托管平臺(tái)上,Dapr 應(yīng)用程序 ID 符合包含目標(biāo)命名空間的有效 FQDN 格式,可以同時(shí)指定:
應(yīng)用 ID (如 nodeapp)
應(yīng)用程序運(yùn)行的命名空間(production)。
比如在 production 命名空間中的 nodeapp 應(yīng)用上調(diào)用 neworder 方法,則可以使用下面的方式:
localhost:3500/v1.0/invoke/nodeapp.production/method/neworder
當(dāng)使用服務(wù)調(diào)用在命名空間中調(diào)用應(yīng)用程序時(shí),我們可以使用命名空間對(duì)其進(jìn)行限定,特別在 Kubernetes 集群中的跨命名空間調(diào)用是非常有用的。
為服務(wù)調(diào)用應(yīng)用訪(fǎng)問(wèn)控制列表配置
訪(fǎng)問(wèn)控制策略在配置文件中被指定,并被應(yīng)用于被調(diào)用應(yīng)用程序的 Dapr sidecar,對(duì)被調(diào)用應(yīng)用程序的訪(fǎng)問(wèn)是基于匹配的策略動(dòng)作,你可以為所有調(diào)用應(yīng)用程序提供一個(gè)默認(rèn)的全局動(dòng)作,如果沒(méi)有指定訪(fǎng)問(wèn)控制策略,默認(rèn)行為是允許所有調(diào)用應(yīng)用程序訪(fǎng)問(wèn)被調(diào)用的應(yīng)用程序。
在具體學(xué)習(xí)訪(fǎng)問(wèn)控制策略配置之前,我們需要先了解兩個(gè)概念:
TrustDomain - “信任域”是管理信任關(guān)系的邏輯組。每個(gè)應(yīng)用程序都分配有一個(gè)信任域,可以在訪(fǎng)問(wèn)控制列表策略規(guī)范中指定。如果未定義策略規(guī)范或指定了空的信任域,則使用默認(rèn)值 public,該信任域用于在 TLS 證書(shū)中生成應(yīng)用程序的身份。
App Identity - Dapr 請(qǐng)求 sentry 服務(wù)為所有應(yīng)用程序生成一個(gè) SPIFFE id,這個(gè) id 附加在 TLS 證書(shū)中。SPIFFE id 的格式為:spiffe://
訪(fǎng)問(wèn)控制策略會(huì)遵循如下所示的一些規(guī)則:
如果未指定訪(fǎng)問(wèn)策略,則默認(rèn)行為是允許所有應(yīng)用訪(fǎng)問(wèn)被調(diào)用應(yīng)用上的所有方法
如果未指定全局默認(rèn)操作且未定義應(yīng)用程序特定策略,則將空訪(fǎng)問(wèn)策略視為未指定訪(fǎng)問(wèn)策略,并且默認(rèn)行為是允許所有應(yīng)用程序訪(fǎng)問(wèn)被調(diào)用應(yīng)用程序上的所有方法
如果未指定全局默認(rèn)操作,但已定義了一些特定于應(yīng)用程序的策略,則會(huì)采用更安全的選項(xiàng),即假設(shè)全局默認(rèn)操作拒絕訪(fǎng)問(wèn)被調(diào)用應(yīng)用程序上的所有方法
如果定義了訪(fǎng)問(wèn)策略并且無(wú)法驗(yàn)證傳入的應(yīng)用程序憑據(jù),則全局默認(rèn)操作將生效
如果傳入應(yīng)用的信任域或命名空間與應(yīng)用策略中指定的值不匹配,則應(yīng)用策略將被忽略并且全局默認(rèn)操作生效
下面是一些使用訪(fǎng)問(wèn)控制列表進(jìn)行服務(wù)調(diào)用的示例場(chǎng)景。
場(chǎng)景 1:拒絕所有應(yīng)用程序的訪(fǎng)問(wèn),除非 trustDomain = public、namespace = default、appId = app1,使用如下所示的配置,允許所有 appId = app1 的調(diào)用方法,并拒絕來(lái)自其他應(yīng)用程序的所有其他調(diào)用請(qǐng)求。
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:deny trustDomain:"public" policies: -appId:app1 defaultAction:allow trustDomain:"public" namespace:"default"
場(chǎng)景 2:拒絕訪(fǎng)問(wèn)除 trustDomain = public、namespace = default、appId = app1、operation = op1 之外的所有應(yīng)用程序,使用此配置僅允許來(lái)自 appId = app1 的方法 op1,并且拒絕來(lái)自所有其他應(yīng)用程序的所有其他方法請(qǐng)求,包括 app1 上的其他方法。
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:deny trustDomain:"public" policies: -appId:app1 defaultAction:deny trustDomain:"public" namespace:"default" operations: -name:/op1 httpVerb:["*"] action:allow
場(chǎng)景 3:拒絕對(duì)所有應(yīng)用程序的訪(fǎng)問(wèn),除非 HTTP 的特定 verb 和 GRPC 的操作匹配,使用如下所示的配置,僅允許以下場(chǎng)景訪(fǎng)問(wèn),并且來(lái)自所有其他應(yīng)用程序的所有其他方法請(qǐng)求(包括 app1 或 app2 上的其他方法)都會(huì)被拒絕。
trustDomain = public、namespace = default、appID = app1、operation = op1、http verb = POST/PUT
trustDomain = “myDomain”、namespace = “ns1”、appID = app2、operation = op2 并且應(yīng)用程序協(xié)議是 GRPC,僅允許來(lái)自 appId = app1 的方法 op1 上的 POST/PUT 請(qǐng)求以及來(lái)自所有其他應(yīng)用程序的所有其他方法請(qǐng)求,包括 app1 上的其他方法,被拒絕
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:deny trustDomain:"public" policies: -appId:app1 defaultAction:deny trustDomain:"public" namespace:"default" operations: -name:/op1 httpVerb:["POST","PUT"] action:allow -appId:app2 defaultAction:deny trustDomain:"myDomain" namespace:"ns1" operations: -name:/op2 action:allow
場(chǎng)景 4:允許訪(fǎng)問(wèn)除 trustDomain = public、namespace = default、appId = app1、operation = /op1/* 所有 http verb 之外的所有方法。
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:allow trustDomain:"public" policies: -appId:app1 defaultAction:allow trustDomain:"public" namespace:"default" operations: -name:/op1/* httpVerb:["*"] action:deny
場(chǎng)景 5:允許訪(fǎng)問(wèn) trustDomain = public、namespace = ns1、appId = app1 的所有方法并拒絕訪(fǎng)問(wèn) trustDomain = public、namespace = ns2、appId = app1 的所有方法,此場(chǎng)景展示了如何指定具有相同應(yīng)用 ID 但屬于不同命名空間的應(yīng)用。
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:allow trustDomain:"public" policies: -appId:app1 defaultAction:allow trustDomain:"public" namespace:"ns1" -appId:app1 defaultAction:deny trustDomain:"public" namespace:"ns2"
場(chǎng)景 6:允許訪(fǎng)問(wèn)除 trustDomain = public、namespace = default、appId = app1、operation = /op1/**/a、所有 http 動(dòng)詞之外的所有方法。
apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:appconfig spec: accessControl: defaultAction:allow trustDomain:"public" policies: -appId:app1 defaultAction:allow trustDomain:"public" namespace:"default" operations: -name:/op1/**/a httpVerb:["*"] action:deny
下面我們通過(guò)一個(gè)具體的示例來(lái)展示下訪(fǎng)問(wèn)控制策略的使用,同樣還是使用 quickstarts 示例中的 hello-world 進(jìn)行說(shuō)明。
gitclone[-b]https://github.com/dapr/quickstarts.git cdquickstarts/tutorials/hello-world/node
hello world
該示例應(yīng)用中包含一個(gè) python 應(yīng)用去調(diào)用一個(gè) node.js 應(yīng)用程序,訪(fǎng)問(wèn)控制列表依靠 Dapr Sentry 服務(wù)來(lái)生成帶有 SPIFFE id 的 TLS 證書(shū)進(jìn)行認(rèn)證,這意味著 Sentry 服務(wù)必須在本地運(yùn)行或部署到你的托管環(huán)境,比如 Kubernetes 集群。
下面的 nodeappconfig 例子顯示了如何拒絕來(lái)自 pythonapp 的 neworder 方法的訪(fǎng)問(wèn),其中 pythonapp 是在 myDomain 信任域和 default 命名空間中,nodeapp 在 public 公共信任域中。
#nodeappconfig.yaml apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:nodeappconfig spec: tracing: samplingRate:"1" accessControl: defaultAction:allow trustDomain:"public" policies: -appId:pythonapp defaultAction:allow trustDomain:"myDomain" namespace:"default" operations: -name:/neworder httpVerb:["POST"] action:deny
#pythonappconfig.yaml apiVersion:dapr.io/v1alpha1 kind:Configuration metadata: name:pythonappconfig spec: tracing: samplingRate:"1" accessControl: defaultAction:allow trustDomain:"myDomain"
接下來(lái)我們先在本地自拓管模式下來(lái)使用啟用訪(fǎng)問(wèn)策略配置,首先需要在啟用 mTLS 的情況下在本地運(yùn)行 Sentry 服務(wù),我們可以直接在 https://github.com/dapr/dapr/releases 頁(yè)面下載對(duì)應(yīng)的 sentry 二進(jìn)制文件,比如我們這里是 Mac M1,則可以使用下面的命令直接下載:
#wgethttps://github.91chi.fun/https://github.com/dapr/dapr/releases/download/v1.8.4/sentry_darwin_arm64.tar.gz $wgethttps://github.com/dapr/dapr/releases/download/v1.8.4/sentry_darwin_arm64.tar.gz $tar-xvfsentry_darwin_arm64.tar.gz
然后為 Sentry 服務(wù)創(chuàng)建一個(gè)目錄以創(chuàng)建自簽名根證書(shū):
$mkdir-p$HOME/.dapr/certs
使用以下命令在本地運(yùn)行 Sentry 服務(wù):
$./sentry--issuer-credentials$HOME/.dapr/certs--trust-domaincluster.local INFO[0000]startingsentrycertificateauthority--version1.8.4--commit18575823c74318c811d6cd6f57ffac76d5debe93instance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4 INFO[0000]configuration:[port]:50001,[castore]:default,[allowedclockskew]:15m0s,[workloadcertttl]:24h0m0sinstance=MBP2022.localscope=dapr.sentry.configtype=logver=1.8.4 WARN[0000]loadingdefaultconfig.couldn'tfindconfigname:daprsystem:statdaprsystem:nosuchfileordirectoryinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4 INFO[0000]startingwatchonfilesystemdirectory:/Users/cnych/.dapr/certsinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4 INFO[0000]certificateauthorityloadedinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4 INFO[0000]rootandissuercertsnotfound:generatingselfsignedCAinstance=MBP2022.localscope=dapr.sentry.catype=logver=1.8.4 #...... INFO[0000]sentrycertificateauthorityisrunning,protectingya'llinstance=MBP2022.localscope=dapr.sentrytype=logver=1.8.4
運(yùn)行成功后 Sentry 服務(wù)將在指定目錄中創(chuàng)建根證書(shū),可以通過(guò)如下所示的命令來(lái)配置環(huán)境變量指定相關(guān)證書(shū)路徑:
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
然后我們就可以運(yùn)行 daprd 為啟用了 mTLS 的 node.js 應(yīng)用啟動(dòng) Dapr sidecar,并引用本地的 Sentry 服務(wù):
daprd--app-idnodeapp--dapr-grpc-port50002-dapr-http-port3501-metrics-port9091--log-leveldebug--app-port3000--enable-mtls--sentry-addresslocalhost:50001--confignodeappconfig.yaml
上面的命令我們通過(guò) --enable-mtls 啟用了 mTLS,通過(guò) --config 指定了上面的 nodeappconfig.yaml 這個(gè)配置文件。
然后啟動(dòng) node.js 應(yīng)用:
$cdnode&&yarn $nodeapp.js NodeApplisteningonport3000!
同樣的方式在另外的終端中設(shè)置環(huán)境變量:
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
然后運(yùn)行 daprd 為啟用了 mTLS 的 python 應(yīng)用啟動(dòng) Dapr sidecar,并引用本地的 Sentry 服務(wù):
daprd--app-idpythonapp--dapr-grpc-port50003--metrics-port9092--log-leveldebug--enable-mtls--sentry-addresslocalhost:50001--configpythonappconfig.yaml
在重新開(kāi)一個(gè)終端直接啟動(dòng) Python 應(yīng)用即可:
$cdpython&&pip3install-rrequirements.txt $python3app.py HTTP403=>{"errorCode":"ERR_DIRECT_INVOKE","message":"failtoinvoke,id:nodeapp,err:rpcerror:code=PermissionDenieddesc=accesscontrolpolicyhasdeniedaccesstoappid:pythonappoperation:neworderverb:POST"} HTTP403=>{"errorCode":"ERR_DIRECT_INVOKE","message":"failtoinvoke,id:nodeapp,err:rpcerror:code=PermissionDenieddesc=accesscontrolpolicyhasdeniedaccesstoappid:pythonappoperation:neworderverb:POST"} #......
由于 nodeappconfig 文件中我們配置了對(duì) /neworder 接口的 POST 拒絕操作,所以應(yīng)該會(huì)在 python 應(yīng)用程序命令提示符中看到對(duì) node.js 應(yīng)用程序的調(diào)用失敗,如果我們將上面的 nodeappconfig 配置中的 action: deny 修改為 action: allow 并重新運(yùn)行應(yīng)用程序,然后我們應(yīng)該會(huì)看到此調(diào)用成功。
對(duì)于 Kubernetes 模式則更簡(jiǎn)單,只需要?jiǎng)?chuàng)建上述配置文件 nodeappconfig.yaml 和 pythonappconfig.yaml 并將其應(yīng)用于 Kubernetes 集群,然后在應(yīng)用的注解中添加 dapr.io/config: "pythonappconfig" 來(lái)指定配置即可開(kāi)啟服務(wù)訪(fǎng)問(wèn)控制。
annotations: dapr.io/enabled:"true" dapr.io/app-id:"pythonapp" dapr.io/config:"pythonappconfig"
Pub/sub 主題范圍訪(fǎng)問(wèn)策略
對(duì)于 Pub/sub 組件,你可以限制允許哪些主題類(lèi)型和應(yīng)用程序發(fā)布和訂閱特定主題。
命名空間或組件范圍可用于限制組件對(duì)特定應(yīng)用程序的訪(fǎng)問(wèn),這些添加到組件的應(yīng)用程序范圍僅限制具有特定 ID 的應(yīng)用程序能夠使用該組件。如下所示顯示了如何將兩個(gè)啟用 Dapr 的應(yīng)用程序(應(yīng)用程序 ID 為 app1 和 app2)授予名為 statestore 的 Redis 組件,該組件本身位于 production 命名空間中:
apiVersion:dapr.io/v1alpha1 kind:Component metadata: name:statestore namespace:production spec: type:state.redis version:v1 metadata: -name:redisHost value:redis-master:6379 scopes: -app1 -app2
除了這個(gè)通用組件的 scopes 范圍之外,發(fā)布/訂閱組件還可以限制以下內(nèi)容:
可以使用哪些主題(發(fā)布或訂閱)
允許哪些應(yīng)用發(fā)布到特定主題
允許哪些應(yīng)用訂閱特定主題
這被稱(chēng)為發(fā)布/訂閱主題范圍。我們可以為每個(gè)發(fā)布/訂閱組件定義發(fā)布/訂閱范圍,比如你可能有一個(gè)名為 pubsub 的 pub/sub 組件,它具有一組范圍,另一個(gè) pubsub2 具有另外不同的范圍。
示例 1:主題訪(fǎng)問(wèn)范圍。如果你的主題包含敏感信息并且僅允許你的應(yīng)用程序的子集發(fā)布或訂閱這些信息,那么限制哪些應(yīng)用程序可以發(fā)布/訂閱主題可能會(huì)很有用。如下以下是三個(gè)應(yīng)用程序和三個(gè)主題的示例:
apiVersion:dapr.io/v1alpha1 kind:Component metadata: name:pubsub spec: type:pubsub.redis version:v1 metadata: -name:redisHost value:"localhost:6379" -name:redisPassword value:"" -name:publishingScopes value:"app1=topic1;app2=topic2,topic3;app3=" -name:subscriptionScopes value:"app2=;app3=topic1"
這里我們?cè)O(shè)置了 publishingScopes 和 subscriptionScopes 兩個(gè)屬性,分別用于配置發(fā)布范圍和訂閱范圍。要拒絕應(yīng)用發(fā)布到任何主題,請(qǐng)將主題列表留空,比如我們這里配置的 app1=topic1;app2=topic2,topic3;app3=,其中的 app3= 就表示該應(yīng)用不允許發(fā)布到任何主題上去。
根據(jù)我們的配置下表顯示了允許哪些應(yīng)用程序發(fā)布到主題中:
| Topic1 | Topic2 | Topic3 | |
|---|---|---|---|
| app1 | X | ||
| app2 | X | X | |
| app3 |
下表顯示了哪些應(yīng)用程序可以訂閱主題:
| Topic1 | Topic2 | Topic3 | |
|---|---|---|---|
| app1 | X | X | X |
| app2 | |||
| app3 | X |
注意:如果未列出應(yīng)用程序(例如,subscriptionScopes 中的 app1),則允許它訂閱所有主題。因?yàn)椴皇褂?allowedTopics 并且 app1 沒(méi)有任何訂閱范圍,所以它也可以使用上面未列出的其他主題。
示例 2:限制允許的主題。如果 Dapr 應(yīng)用程序向其發(fā)送消息,則會(huì)創(chuàng)建一個(gè)主題,在某些情況下,應(yīng)管理此主題的創(chuàng)建。例如:
Dapr 應(yīng)用程序中生成主題名稱(chēng)的錯(cuò)誤可能導(dǎo)致創(chuàng)建無(wú)限數(shù)量的主題
精簡(jiǎn)主題名稱(chēng)和總數(shù),防止主題無(wú)限增長(zhǎng)
在這些情況下,可以使用 allowedTopics 屬性進(jìn)行配置,以下就是三個(gè)允許主題的示例:
apiVersion:dapr.io/v1alpha1 kind:Component metadata: name:pubsub spec: type:pubsub.redis version:v1 metadata: -name:redisHost value:"localhost:6379" -name:redisPassword value:"" -name:allowedTopics value:"topic1,topic2,topic3"
示例 3:組合 allowedTopics 和范圍。有時(shí)你想結(jié)合這兩個(gè)范圍,因此只有一組固定的允許主題并為某些應(yīng)用程序指定范圍。以下是三個(gè)應(yīng)用程序和兩個(gè)主題的示例:
apiVersion:dapr.io/v1alpha1 kind:Component metadata: name:pubsub spec: type:pubsub.redis version:v1 metadata: -name:redisHost value:"localhost:6379" -name:redisPassword value:"" -name:allowedTopics value:"A,B" -name:publishingScopes value:"app1=A" -name:subscriptionScopes value:"app1=;app2=A"
注意這里我們沒(méi)有列出第三個(gè)應(yīng)用程序,如果沒(méi)有在范圍內(nèi)指定應(yīng)用程序,則允許它使用所有主題。
根據(jù)上面的配置下表顯示了允許哪個(gè)應(yīng)用程序發(fā)布到主題中:
| A | B | C | |
|---|---|---|---|
| app1 | X | ||
| app2 | X | X | |
| app3 | X | X |
下表顯示了允許哪個(gè)應(yīng)用程序訂閱主題:
| A | B | C | |
|---|---|---|---|
| app1 | |||
| app2 | X | ||
| app3 | X | X |
審核編輯:湯梓紅
-
API
+關(guān)注
關(guān)注
2文章
2280瀏覽量
66530 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3343瀏覽量
60096
原文標(biāo)題:Dapr 安全性之訪(fǎng)問(wèn)控制策略
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
分布式軟件系統(tǒng)
分布式光伏發(fā)電安全性
分布式系統(tǒng)的優(yōu)勢(shì)是什么?
HarmonyOS應(yīng)用開(kāi)發(fā)-分布式設(shè)計(jì)
HarmonyOS分布式數(shù)據(jù)庫(kù),為啥這么牛?
計(jì)及分布式發(fā)電的配電網(wǎng)潮流計(jì)算 精選資料分享
各種分布式電源的電氣特性
HDC2021技術(shù)分論壇:分布式調(diào)試、調(diào)優(yōu)能力解決方案
HDC2021技術(shù)分論壇:如何高效完成HarmonyOS分布式應(yīng)用測(cè)試?
如何高效完成HarmonyOS分布式應(yīng)用測(cè)試?
分布式軟總線(xiàn)實(shí)現(xiàn)近場(chǎng)設(shè)備間統(tǒng)一的分布式通信管理能力如何?
OpenHarmony 3.1 Beta版本關(guān)鍵特性解析——分布式DeviceProfile
OpenHarmony技術(shù)論壇:分布式相機(jī)和分布式圖庫(kù)功能
分布式應(yīng)用中使用Dapr時(shí)的安全特性和能力
評(píng)論