Envoy CORS
CORS
-
跨域资源共享(CORS) 是HTTP的访问控制机制
- 它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源
- 当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求
- 比如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 http://domain-b.com/image.jpg;网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源;
-
出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求
-
例如,XMLHttpRequest和Fetch API遵循同源策略
- 这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头
-
- 跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行
Envoy跨域资源共享
- CORS是一种通过指定能够访问当前域的那些特定的或所有路由而来的外部域来强制对资源进行客户端访问控制的方法;
-
出于安全方面的原因,浏览器会限制从脚本发起的跨域HTTP请求,
-
因而,浏览器使用HTTP标头的存在来确定是否允许来自不同来源的响应;
-
-
Envoy的cors过滤器用于许可Web应用服务器进行跨域访问控制
-
通过在HTTP标头中追加一些额外的信息来通知浏览器允许跨域访问
-
CORS相关参数
查看代码
--
listeners:
...
filter_chains:
filter_chain_match: {...}
filters:
name: ...
typed_config: ...
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
...
route_config:
name: ...
virtual_hosts:
...
cors: # 虚拟主机 CORS 策略。
"allow_origin_regex": [] # 正则表达式模式表示的允许共享的资源
"allow_methods": "..." # 允许资源访问时使用的HTTP方法列表,内容将被序列化到access-control-allow-methods标头;
"allow_headers": "..." # 允许在请求资源时使用HTTP标头列表,内容将被序列化到access-control-allow-headers标头;
"expose_headers": "..." # 浏览器可访问的HTTP标头白名单,内容将被序列化到access-control-expose-headers标头;
"max_age": "..." # 请求的缓存时长,内容将被序列化到access-control-max-age标头;
"allow_credentials": "{...}" # 布尔型值,是否允许服务调用方法使用凭据发起实际请求;
"enabled": "{...}" # 布尔型值,是否启用CORS,默认为启用;此参数即将启用,并由filter_enabled取代;
"filter_enabled": "{...}" # 是否启用CORS过滤器,若启用,此处需要定义启用此过滤器的请求百分比,默认为100/HUNDRED;
default_value:
numerator: ...
denominator: ...
runtime_key: ...
"shadow_enabled": "{...}" # 是否仅在阴影模式下启用过滤器的请求的百分比,若启用,其默认值为100/HUNDRED;若启用,它将评估请求的来源以确定其是否有效,但不强制执行任何策略;若同时启用了filter_enabled和shadow_enabled,则filter_enabled标志优先;
routes: # 路由条目,匹配到当前虚拟主机的请求中的path匹配检测将针对各route中由match定义条件进行;
...
route: # 常用内嵌字段cluster|cluster_header|weighted_clusters,基于集群、请求报文中的集群标头或加权集群(流量分割)定义路由目标;
...
cors: # 跨域资源共享(Cross Origin Resource Sharing);
"allow_origin_regex": [] # 正则表达式模式表示的允许共享的资源
"allow_methods": "..." # 允许资源访问时使用的HTTP方法列表,内容将被序列化到access-control-allow-methods标头;
"allow_headers": "..." # 允许在请求资源时使用HTTP标头列表,内容将被序列化到access-control-allow-headers标头;
"expose_headers": "..." # 浏览器可访问的HTTP标头白名单,内容将被序列化到access-control-expose-headers标头;
"max_age": "..." # 请求的缓存时长,内容将被序列化到access-control-max-age标头;
"allow_credentials": "{...}" # 布尔型值,是否允许服务调用方法使用凭据发起实际请求;
"enabled": "{...}" # 布尔型值,是否启用CORS,默认为启用;此参数即将启用,并由filter_enabled取代;
"filter_enabled": "{...}" # 是否启用CORS过滤器,若启用,此处需要定义启用此过滤器的请求百分比,默认为100/HUNDRED;
default_value:
numerator: ...
denominator: ...
runtime_key: ...
"shadow_enabled": "{...}" # 是否仅在阴影模式下启用过滤器的请求的百分比,若启用,其默认值为100/HUNDRED;若启用,它将评估请求的来源以确定其是否有效,但不强制执行任何策略;若同时启用了filter_enabled和shadow_enabled,则filter_enabled标志优先;
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
配置跨域资源共享
-
CORS过滤器支持两种运行时设定
-
filter_enabled:在请求上启用过滤器的百分比,默认为100/HUNDRED;
-
设置filter_enabled参数的runtime_key的值可在运行时启用或禁用CROS过滤器;
-
- shadow_enabled:于影子模式下在请求上启用CORS过滤器的百分比,默认值为0;用于评估请求的Origin以确定它是否有效,但并不会强制任何策略;
-
设置shadow_enabled参数的runtime_key的值可在运行时启用或禁用CROS过滤器;
-
-
过滤器启用与否,可通过admin接口的/runtime获取;
- 如果filter_enabled和shadow_enabled同时启用,则filter_enabled优先级高于shadow_enabled;
-
-
Envoy的cors机制需要按如下方式配置
-
在过滤器列表中定义cors过滤器;
-
在虚拟主机或路由中配置cors策略
-
禁用:禁用CORS
-
启用:启用CORS,且允许的请求者为*
-
受限:启用CORS,且允许的请求者需要自定义
-
-
CORS配置示例
front-envoy.yaml
admin:
access_log_path: "/dev/null"
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: admin
admin_layer: {}
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
codec_type: auto
stat_prefix: ingress_http
access_log:
- name: envoy.file_access_log
typed_config:
"@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog
path: "/var/log/access.log"
route_config:
name: local_route
virtual_hosts:
- name: www
domains:
- "*"
cors:
allow_origin:
- "*"
allow_methods: "GET"
filter_enabled:
default_value:
numerator: 100
denominator: HUNDRED
runtime_key: cors.www.enabled
shadow_enabled:
default_value:
numerator: 0
denominator: HUNDRED
runtime_key: cors.www.shadow_enabled
routes:
- match:
prefix: "/cors/open"
route:
cluster: backend_service
- match:
prefix: "/cors/disabled"
route:
cluster: backend_service
cors:
filter_enabled:
default_value:
numerator: 0
denominator: HUNDRED
- match:
prefix: "/cors/restricted"
route:
cluster: backend_service
cors:
allow_origin:
- "envoyproxy.io"
allow_methods: "GET"
- match:
prefix: "/"
route:
cluster: backend_service
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: envoy.filters.http.cors
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
clusters:
- name: backend_service
connect_timeout: 0.25s
type: strict_dns
lb_policy: round_robin
http2_protocol_options: {}
load_assignment:
cluster_name: backend_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backendservice
port_value: 80
动态调整
filter_enabled
# curl -XPOST http://envoy_ip:9901/runtime_modify?cors.www.enabled=90
shadow_enabled
# curl -XPOST http://envoy_ip:9901/runtime_modify?cors.www.shadow_enabled=90
参考文档
https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/cors_filter
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-corspolicy
https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/cors/v3/cors.proto#extension-envoy-filters-http-cors