记录:尝试 HashiCorp Vault + AWS IAM + AWS Lambda
Vault 是 HashiCorp 开源的密钥库程序。
从 https://www.vaultproject.io/downloads 下载得到的 CLI 程序包括既包括客户端也包括服务端实现。
本文以 Windows + PowerShell + Nodejs 为环境描述用法,其它环境基本相同。
Vault 基本用法
运行开发服务器:
vault server -dev
开发服务器会直接使用 HTTP 而不启用 HTTPS,在 http://127.0.0.1:8200 。
开发服务器会默认启用 Vault UI,在 http://127.0.0.1:8200/ui 。
根据运行后的提示,客户端的用法是:
$env:VAULT_ADDR="http://127.0.0.1:8200" vault status vault auth list
静态的密钥读写:
vault kv put secret/hello foo=1 bar=a vault kv get secret/hello
这里的 secret
是一个默认的存储库(Secret Engine),hello
是具体的密钥,而 foo bar
是密钥中的多组键值对。
vault secrets list vault kv list secret/
密钥可以删除,删除后能读出来被删除的元信息。
vault kv delete secret/hello vault kv get secret/hello
虽然 CLI 提供了 vault kv
命令,但其实 API 只有 read
接口,CLI 也提供它。这都有助于本地实验。
vault read secret/data/hello
Vault SDK 用法
Vault 官方不提供 Node.js SDK。有一个相当完整的第三方库 node-vault
。
基本用法:
const NodeVault = require('node-vault'); const vault = NodeVault({ apiVersion: 'v1', endpoint: 'http://127.0.0.1:8200', token: 'xxx', }); if (require.main === module) { (async () => { const res = await vault.read('secret/data/hello'); console.log(res); })(); }
场景与集成过程
如果在 AWS Lambda 中想使用某个密钥,第一个想法是从环境变量传进来。但这样会产生一个风险,因为可能很多 AWS 子账号都能看到这个信息。
同理,按上述的 SDK 基本用法传 VAULT_TOKEN
,问题是一样的。
Vault 利用了 AWS STS 提供的 GetCallerIdentity
接口,设计了一个身份验证方式,并在验证成功后生成一个临时 token 用于访问。这称为 IAM 鉴权方式,是为了区别于另一种基于 EC2 的鉴权方式。
首先,在 AWS IAM 中创建一个新的 lambda role,并附加以下策略(Policies):
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "iam:GetUser", "iam:GetRole", "sts:GetCallerIdentity" ], "Effect": "Allow", "Resource": "*" } ] }
你会得到一个 role arn。
vault auth enable aws vault write auth/aws/role/dev-iam ` auth_type=iam ` bound_iam_principal_arn=$ARN_ROLE ` token_policies=default ` token_ttl=600s
这里的 dev-iam
是 Vault Role,default
是 Vault Policy,token_ttl
是临时 token 的有效期。
接下来是限定 AWS 凭据范围,减轻重放攻击的一个配置:
vault write auth/aws/config/client iam_server_id_header_value=dev
然后,我们需要生成一个有效的 AWS STS GetCallerIdentity 请求,但不由 AWS SDK 发起,而是传给 Vault 使用,借此换取临时的 Vault token。
事实上 AWS SDK 不直接提供这个能力,虽然一切细节都是公开的。
const sts = new AWS.STS(); function getAwsRequest(iamServerId) { const request = sts.getCallerIdentity(); request.httpRequest.headers['X-Vault-AWS-IAM-Server-ID'] = iamServerId; // configured in vault request.emit('build', [request]); request.emit('afterBuild', [request]); request.emit('sign', [request]); // console.log(request.httpRequest); return request.httpRequest; } function toGolangStyleHeaders(headers) { const ret = {}; for (const [k,v] of Object.entries(headers)) { ret[k] = [v]; } return ret; } function toVaultRequest(request) { // console.log(request); const encoded_url = Buffer.from(request.endpoint.href, 'utf-8').toString('base64'); const encoded_body = Buffer.from(request.body, 'utf-8').toString('base64'); const golang_headers = toGolangStyleHeaders(request.headers); const encoded_headers = Buffer.from(JSON.stringify(golang_headers), 'utf-8').toString('base64'); return { 'role': 'dev-iam', // Vault Role 'iam_http_request_method': request.method, 'iam_request_url': encoded_url, 'iam_request_body': encoded_body, 'iam_request_headers': encoded_headers, } } async function awsLoginVault() { const iamServerId = 'dev'; const awsRequest = getAwsRequest(iamServerId); const vaultRequest = toVaultRequest(awsRequest); const response = await vault.awsIamLogin(vaultRequest); // console.log(response); vault.token = response.auth.client_token; // const status = await vault.status(); // console.log(status); }
事实上这里得到的 vaultRequest
也能使用 CLI 试用:
vault write auth/aws/login \ role=dev-role-iam \ iam_http_request_method=POST \ iam_request_url=$encoded_url \ iam_request_body=$encoded_body \ iam_request_headers=$encoded_headers
测试之:
async function getVaultSecret() { const response = await vault.read('secret/data/hello'); // console.log(response); return response.data.data; }
失败了,很正常,还差一步。
上文选择了使用 default
policy,但默认地,在这个 policy 中并未配置对 secret/*
的访问权。
vault policy list vault policy read default > default-policy.hcl // 根据下文修改文件 vault policy write default default-policy.hcl
在 default-policy.hcl
中追加一段:
path "secret/*" { capabilities = ["read"] }
再试一次,大功告成。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一文搞懂hadoop的metrics
【概述】 一个成熟的项目通常都会自带提供metric,反映运行时内部的各个信息,以方便进行监控运维。hadoop也不例外,通过jmx可以查看内部各个metrics信息,本文就来聊聊hdfs的metrics。 【Metrics指标查询】 hdfs的metrics通过jmx获取,具体可以通过http的方式获取,也可以通过命令行的方式来获取。 通过http的方式获取,可以全量获取所有jmx的指标项,也可以精确获取指定组件服务的指定模块的指定指标项。 对于全量获取,其请求的URL格式为: http://$IP:$PORT/jmx 其中IP、PORT为对应组件服务http的监听ip、端口。以nn为例,端口默认为50070。 而对于精准获取,其请求的URL格式为: http://$IP:$PORT/jmx?get=MXBeanName::AttributeName 其中MXBeanName的格式为:"Hadoop:service=$ServiceName,name=$Name" ServiceName为组件服务的名称,对于hdfs而言就是NameNode、DataNode、JournalNode;...
- 下一篇
PHP:草根创业的最爱
PSI - https://gitee.com/crm8000/PSI 是我们的创业项目,其后台开发语言是PHP。 最终选择PHP的过程 1. PSI的起源 2013年,在一个物流项目中,首次用了PSI这个项目名称,这应该是PSI起源的最初了。该项目是用C#写的(有趣的是,该项目的前端框架一直沿用到今天)。 2014年圣诞节前后,用Groovy写的PSI原型完工。这次PSI是进销存项目了。原本是计划用Java写的,但是在习惯了C#后,在品味方面实在是不能接受Java的某些风格,所以就找到了Groovy这个替代品(题外话,如果当时有.net core的话,就没有后面的故事了)。 时间到了2015年,Gitee联合魔泊云,一起推广研发和部署一体化的解决方案。当我们把PSI部署到魔泊云后,发现Groovy写的程序没法运行。这自然是我们当初技术稀烂,就找Groovy背锅,决定换一种开发语言。 最后的选择是PHP。 娶了红玫瑰,久而久之,红的变了墙上的一抹蚊子血,白的还是“床前明月光”;娶了白玫瑰,白的便是衣服上沾的一粒饭粘子,红的却是心口上一颗朱砂痣。 C#与PHP,白玫瑰与红玫瑰。 2. 黑...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- 2048小游戏-低调大师作品
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7安装Docker,走上虚拟化容器引擎之路