Amazon Web Services (AWS) 中对于其资源的访问绝大部分都是通过它的IAM来控制的,简单来说IAM定义了哪个资源或者哪个User/Role可以在什么情况下对于哪些Resource可以进行或阻止哪些Action,比如下面这个简单的IAM Policy就定义了一个可以获取alice-perl-bucket中所有Object的Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AliceCanGetAllHerObjects",
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::alice-perl-bucket/*"]
}
]
}
这样的Policy可以贴在一个IAM User或者Role身上,然后这个User或者Role便可以在正常情况下获取alice-perl-bucket中的Object。那么用户怎么来使用这些Policy呢?一般就是两种途径,一是登录AWS控制台,成功之后AWS自动会根据User或者Role所有的Policy来显示或者屏蔽某些资源,但是GUI中会涉及很多潜在的Action,所以看到很多奇怪的错误或者空白都是很常见的。第二种也称为编程访问,不会涉及GUI,需通过SDK或者CLI来向AWS发送HTTP请求来获取资源或者行操作,比如”aws s3 get s3://alice-perl-bucket/secret-file.txt"。这是会有人问这种方式难道不需要验证身份吗?当然不可能,只是不需要用户特别明确的来做而已。
每次编程访问时,HTTP请求中除了真正的内容,还会附上一个ACCESS_KEY_ID和一个用于身份验证的通过一个SECRET_KEY对于内容进行的数字签名。当AWS收到请求后会根据ACCESS_KEY_ID来获取真正的ACCESS_KEY并且验证签名,通过后再看请求的内容。那么ACCES_KEY和SECRET_KEY哪来的呢?每次在AWS生成新的User时,可以选择来生成这样一对密钥,但是SECRET_KEY只在此时可见,需要用户妥善记录下来,之后便不在可以获取,而且SECRET_KEY在之后使用中不会以任何方式出现在任何地方。也就是说任何人或者机器只要有了一对这样的密钥,便可以像AWS索取被允许的资源。其实AWS的资源也可以通过被赋予Role来获取对其他资源的访问,但其实现原理最后也会回到这样的一对密钥上,所以这里不会区别对待。(这篇不会详述User和Role的区别,更不会提及什么Identity Federation,其实Vault的AWS Secret引擎也分不同的模式,下面先从最直白的开始)
相信此刻具体什么是AWS的动态凭据已经很明了了,但Vault要如何来动态的生成一对对密钥呢?IAM User本身其实也是一种AWS资源,只要有了足够的权限就可以被生成,所以Vault采用的方式很简单粗暴,即使用一个可以生成IAM User的密钥对来生成更多的IAM User和密钥对。启动了aws引擎之后的第一步便是给Vault提供一个能够生成IAM User的密钥对,我们姑且称它为root-key-pair:
vault secrets enable -path=my-aws-path aws # 使用my-aws-path
vault secrets list
vault path-help my-aws-path # 看看都有哪些字段
vault write my-aws-path/config/root \
access_key=xxxxxxxxxxx \
secret_key=yyyyyyyyyyy \
region=us-east-1 # xxxxx 和 yyyyy即密钥对
vault read my-aws-path/config/root #无缘再见secret_key
成功后就可以开始动态的创建各种各样的IAM User了。比如说我们想创建一个能够媲美alice-perl的IAM User,并且获得一对新的密钥对来访问S3。首先先是要定义一个Vault中的aws Role,这个Role非IAM Role,且称它为alice-perl-like-role,并且要告诉Vault说这个Role拥有什么样的IAM权限。
vault write my-aws-path/roles/alice-perl-like-role credential_type=iam_user policy_document=@al-s3-policy.json
vault read my-aws-path/roles/alice-perl-like-role # confirm the policy
这里的al-s3-policy.json便是上面的那个IAM Policy。此时我们的Vault中便有了一个新的Role,接下来便可以用它来生成新的密钥对了:
vault read my-aws-path/creds/alice-perl-like-role # 生成一个新的用户并获取它的密钥对
vault read my-aws-path/creds/alice-perl-like-role # 再来一个
这里能看出这两次生成的密钥对是不同的,此时可以登录aws的IAM来看一下新的用户们:
和他们的Policy:
此时的密钥对便可以用来访问alice-perl-bucket中的Object了。那么如果我要做的事情结束了,我要怎么样来清理门户呢?Vault也可以自动来做这个事情,通过对于这个lease的revoke可以顺便删除新生成的IAM User:
vault lease revoke my-aws-path/creds/alice-perl-like-role/4rvxPxaUqvS1oUUPEVz5r7rV
此时可以查看AWS,会发现对应的那个User也被删除了。Vault也会在lease过期时执行同样的操作。
最后还要补充一点,虽然跟Vault没什么关系,但也是要注意的。使用root-key-pair创建出来的IAM policy是不能超出root-key-pair本身的权限的。比如说,如果root-key-pair中只允许访问alice-perl-bucket,那么他是无法生成对于别的bucket的Policy的。这个其实很合理,总不能说我可以创建出超越自己认知的东西吧。