AWS Secrets Manager 踩坑記

最近項(xiàng)目上在引入AWS Secrets Manager作為RDS密碼管理以取代直接將密碼放在config中的實(shí)現(xiàn)烘绽,同時(shí)要加入secretsmanger的password auto-rotation嘿辟,看似平平無奇的功能例诀,卻著實(shí)讓人踩了很多坑,所以我決定吧這個(gè)悲傷的故事寫成一篇博客(因?yàn)槲业牟┛蚑MD一年沒更新了)菇民。

首先來看看secretsmanger是什么呢禁筏?顧名思義持钉,就是一個(gè)管理的密碼serverless的服務(wù),將通常保存在配置文件中的敏感數(shù)據(jù)如密碼篱昔,用戶名保存到secretsmanger中每强,可以是諸如數(shù)據(jù)庫(kù)連接憑證,也可以單純的存儲(chǔ)其它的第三方登錄憑證州刽。

AWS Secrets Manager helps you protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle.

AWS Secrets Manager 以key/value pair的方式存儲(chǔ)secrets的內(nèi)容空执,同時(shí)支持secrets cross region replication,rotation等穗椅, 目前很多aws的服務(wù)如RDS等都支持了rotation功能辨绊,第三方的secrets也可以通過實(shí)現(xiàn)自己的lambda進(jìn)行rotaion。

為什么要用secretsmanager

我一直信奉大道至簡(jiǎn)的理念匹表,如果沒有迫切的需求或切實(shí)的收益而增加一個(gè)依賴或服務(wù)门坷,就是徒增(腦)煩惱(殘)。

所以為什么要加入它呢袍镀?

  1. 增加安全性:顯而易見默蚌,敏感信息將不再存儲(chǔ)在代碼中,同時(shí)如果項(xiàng)目也是構(gòu)建在AWS之上的苇羡,那么于其它服務(wù)的深度集成也是十分便利的

  2. 地區(qū)法律或規(guī)定的要求:可能受制于地方法律

  3. 或在項(xiàng)目合同要求密碼需要rotaion绸吸,audit等等功能,自己再去實(shí)現(xiàn)這些東西顯然是不現(xiàn)實(shí)的。

  4. 便于多服務(wù)下的統(tǒng)一密碼管理锦茁,對(duì)應(yīng)于微服務(wù)或serverless的場(chǎng)景

先來回國(guó)一下, 在沒有引入諸如secretsmanager服務(wù)之前攘轩,我們通常如何管理密碼的呢?

  1. 純文本存儲(chǔ)

    一般的項(xiàng)目有可能直接就將密碼存到config中码俩,可能并不加密(真實(shí)case撑刺,并不是編出來的),出于安全考慮握玛,這個(gè)config一般不會(huì)被git trace够傍,當(dāng)然頭鐵放進(jìn)去在天朝也不違法。那這樣的安全問題就顯而易見挠铲,代碼泄露或者服務(wù)器被偷都會(huì)將密碼冕屯。

    但是,這就是爛的設(shè)計(jì)嗎拂苹?我覺得不一定安聘,至少分情況:如果一個(gè)應(yīng)用的安全要求并沒有太高,如這個(gè)博客應(yīng)用瓢棒,這樣的設(shè)計(jì)我認(rèn)為恰好是合適的,我發(fā)了篇文章手動(dòng)備個(gè)份浴韭,即便整個(gè)被黑了還不是重新部署一下的事情。如果引入我下面舉例的實(shí)現(xiàn)脯宿,安全性提升帶來的收益并不與付出和復(fù)雜性相等念颈。所以我認(rèn)為這樣的方式也是有其應(yīng)用場(chǎng)景與價(jià)值的。

  2. 環(huán)境變量載入

    將密碼作為環(huán)境變量進(jìn)行載人连霉,在container或主機(jī)終止時(shí)榴芳,密碼信息便無法獲取,非敏感配置便可以放到config中并加入version control中跺撼。這樣做就需要在服務(wù)或容器或主機(jī)啟動(dòng)時(shí)主動(dòng)注入環(huán)境變量窟感,如果集成了如github action這樣可以支持密碼存儲(chǔ)的CI/CD工具,那么也可以以比較方便且安全的方式將密碼信息注入到環(huán)境變量中歉井。但如果手動(dòng)部署(不要奇怪柿祈,即便2022,不是所有項(xiàng)目都前后分離哩至,也不是所有項(xiàng)目都有CI/CD), 那么啟動(dòng)參數(shù)將會(huì)爆炸躏嚎。

  3. 存儲(chǔ)加密密碼文本

    在這種方式下我們將敏感信息通過密鑰進(jìn)行加密,在容器&服務(wù)啟動(dòng)或在密碼需要被使用時(shí)進(jìn)行解密憨募,解密的密鑰一般也可以通過環(huán)境變量在容器&服務(wù)啟動(dòng)時(shí)注入紧索。

  4. config server

    可以將密碼等信息統(tǒng)一的存儲(chǔ)到config server中如Spring Cloud Config,與應(yīng)用服務(wù)相解耦菜谣,減少脫庫(kù)泄露密碼的風(fēng)險(xiǎn)珠漂,同時(shí)晚缩,config server在微服務(wù)的項(xiàng)目中可以有效的減少密碼和其它配置信息的冗余。

  5. Secrets-manager platform

    相較于config server媳危,secrets-manager 更關(guān)注于密碼存儲(chǔ)的安全性荞彼,如加入secrets-manager自己的ACL, audit, secrets-rotation等功能,同時(shí)復(fù)雜度也會(huì)進(jìn)一步的提升待笑。AWS Secrets Manager 便是其中的一種鸣皂,還有如Valut等(就是為了舉例搜到的,我也沒用過)暮蹂。

怎么用AWS Secrets Manager

secrets-manager的使用看上去還是很簡(jiǎn)單的寞缝,如果你使用過其它AWS的服務(wù),那么它的套路也是熟悉的配方仰泻,我們可以通過下面的cloudformation來看一下一個(gè)比較完整的case:

也可以參考官方文檔中的sample

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::SecretsManager-2020-07-23

Parameters:
  DatabaseARN:
    Type: String
  KmsKeyARN:
    Type: String
    SecurityGroup:
        Type: String
    VpcSubnets:
        Type: String
    
Resources:
  PostgresSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: secretsName
      KmsKeyId: !Ref KmsKeyARN
      GenerateSecretString:
        SecretStringTemplate: !Sub '{"username": "postgres", "dbname": "postgres","ssl": false}'
        GenerateStringKey: password
        PasswordLength: 12
        ExcludeCharacters: "\"@/\\"
  PostgresAttachment:
    Type: AWS::SecretsManager::SecretTargetAttachment
    Properties:
      SecretId: !Ref PostgresSecret
      TargetId: !Ref DatabaseARN
      TargetType: AWS::RDS::DBInstance
  PostgresSecretRotation:
    Type: AWS::SecretsManager::RotationSchedule
    DependsOn: PostgresAttachment
    Properties:
      SecretId: !Ref PostgresSecret
      HostedRotationLambda:
        RotationType: PostgreSQLSingleUser
        RotationLambdaName: PostgreSecretsManagerRotationLambda
        KmsKeyArn: !Ref KmsKeyARN
        VpcSecurityGroupIds: !Ref SecurityGroup
        VpcSubnetIds: !Ref VpcSubnets
      RotationRules:
        AutomaticallyAfterDays: 60

從以上的sample中我們可以看到主要有三個(gè)resource: 密碼自身荆陆、與RDS attach,以及rotation的需要的資源。我們可以逐個(gè)分析一下

  1. AWS::SecretsManager::Secret

    密碼自身集侯,可以看到上面的sample中密碼是自動(dòng)生成的被啼,我們只是做了簡(jiǎn)單的規(guī)約。同時(shí)我們需要指定一個(gè)kms 對(duì)我們的secrets進(jìn)行加密棠枉。

    這里比較tricky的一點(diǎn)是浓体,如果我們想要只想存儲(chǔ)一個(gè)非rotation的密碼,是沒辦法直接在cloudformation中完成的辈讶,我們不能把密碼直接寫在cloudformation中命浴,即便用參數(shù)的方式傳入,stack上的parameter是明文顯示的荞估,所以如只是存儲(chǔ)非rotaiton的secrets咳促,最好在stack生成之后在console上手動(dòng)update。

  2. AWS::SecretsManager::SecretTargetAttachment

    該資源用于將創(chuàng)建的secrets與數(shù)據(jù)庫(kù)進(jìn)行相關(guān)聯(lián)勘伺,secrets manage目前可以支持一下服務(wù)的attach和rotaion:

    • Amazon Aurora on Amazon RDS

    • MySQL on Amazon RDS

    • PostgreSQL on Amazon RDS

    • Oracle on Amazon RDS

    • MariaDB on Amazon RDS

    • Microsoft SQL Server on Amazon RDS

    • Amazon DocumentDB

    • Amazon Redshift

  3. AWS::SecretsManager::RotationSchedule

    定義secrets rotaion的規(guī)則。上面列出的服務(wù)都已經(jīng)很好的支持的rotation褂删,WAS官方提供了lamba的實(shí)現(xiàn)飞醉,HostedRotationLambda 會(huì)啟動(dòng)一個(gè)Nested lamba來進(jìn)行roation,你只需要配置好相關(guān)的參數(shù)即可屯阀。如果需要對(duì)非上述服務(wù)的密碼或第三方的其它密碼也進(jìn)行rotaiton缅帘,則需要顯示部署一個(gè)進(jìn)行rotaion的lambda來實(shí)現(xiàn)rotaiton。需要為rotaitonlambda指定相應(yīng)的secuirty group和subnets使其可以訪問目標(biāo)服務(wù)难衰。

遇到了哪些坑钦无?

上面的一切都看似簡(jiǎn)單且美好,但在使用它之前你可能需要看看我遇到的這些坑.

  1. 對(duì)于已經(jīng)存在的用戶盖袭,需要在第一次進(jìn)行鏈接時(shí)手動(dòng)更新密碼

    一般使用這些服務(wù)時(shí)可能都會(huì)有As code(infrastructure as code)的要求, 我們?nèi)绻苯訉⒚艽ahard code到cloudformation或者以參數(shù)的方式傳入失暂,那么密碼都是可見的彼宠,顯然不能這樣做,所以可能都需要使用GenerateSecretString的方式弟塞。如果是創(chuàng)建一個(gè)新的用戶和密碼凭峡,那是沒問題的,但是如果是為一個(gè)已經(jīng)存在的用戶進(jìn)行配置决记,那么就會(huì)有問題摧冀,因?yàn)樵撚脩艉兔艽a已經(jīng)存在,且密碼和generate出來的那個(gè)不一樣系宫,這樣secrets-manager便無法連接到目標(biāo)服務(wù)索昂。如果enable了auto-rotation,那么在stack創(chuàng)建時(shí)就會(huì)自動(dòng)進(jìn)行一次rotation扩借,因?yàn)檫B接無法成功楼镐,所以rotation也會(huì)失敗。因此在第一次stack創(chuàng)建時(shí)往枷,就得手動(dòng)的將服務(wù)的密碼更新為generate出來的那個(gè)框产,這樣secrets-manager才可以成功進(jìn)行鏈接和rotation。但這顯然不是一個(gè)好的實(shí)踐错洁,也沒找到什么好的辦法秉宿,好在只是在第一次stack創(chuàng)建時(shí)需要的操作。

  2. 無法指定具體的rotation time

    我們?cè)谏厦娴腸loudformation中可以看到在enable auto-rotation的時(shí)候指定了AutomaticallyAfterDays, 那么secrets-manager會(huì)在指定N天后的什么時(shí)候發(fā)生rotation呢屯碴?答案就是鬼知道描睦,aws會(huì)在那一天的隨機(jī)一個(gè)時(shí)刻進(jìn)行更新,但總之我們是不可控的导而,所以最大可能有48h的一個(gè)時(shí)間差忱叭。但從文檔上看現(xiàn)在如果不使用cloudformation是可以指定具體的更新時(shí)間的,可以指定一個(gè)cronjob的expression今艺,但cloudformation不支持就很奇怪韵丑,如果建好了在去手動(dòng)更改,那As code不成了笑話了虚缎,撵彻,

  3. service無法被告知password rotation

    當(dāng)我們將secrets migrate到secrets-manager之后,應(yīng)用服務(wù)就不需要在存儲(chǔ)密文或者加密之后的密文啦实牡,那么我們?nèi)绾潍@取密文呢陌僵?aws給出的方案是用aws-sdk進(jìn)行獲取,本質(zhì)就是一個(gè)http請(qǐng)求创坞,只需要給需要密文的服務(wù)secretsmanager:GetSecretValue的權(quán)限就可以了碗短。但讓人難受的是,http 是無狀態(tài)的题涨,如果我們開啟了auto-rotation偎谁,我們需要主動(dòng)去請(qǐng)求secrets-manager獲取最新的密碼信息总滩。更坑的是由于第二點(diǎn)所說的我們無法指定具體的rotation時(shí)間,這就意味著應(yīng)用服務(wù)可能會(huì)有downtime搭盾。

怎么填坑咳秉?

從上面那幾個(gè)坑中,影響最大的可能就是第三個(gè)坑了鸯隅,因?yàn)槿绻肓艘粋€(gè)新的服務(wù)帶來的居然是downtime的話澜建,顯然是無法讓人接受的。那么怎么去解決這個(gè)問題呢蝌以?

  1. 雙用戶

    這也是aws官方給出的一個(gè)解決方案炕舵,比如對(duì)一個(gè)數(shù)據(jù)庫(kù)給應(yīng)用服務(wù)兩個(gè)用戶,兩個(gè)用戶的rotaiton時(shí)間一致跟畅,但是有幾天的間隔咽筋,比如都是都是每60天rotation一次,然后連個(gè)用戶的創(chuàng)建時(shí)間隔個(gè)十天二十天徊件。應(yīng)用服務(wù)同一時(shí)刻只會(huì)使用一個(gè)用戶奸攻,在應(yīng)用服務(wù)啟動(dòng)時(shí)可以獲取最近進(jìn)行了rotation的用戶建立連接池,同時(shí)設(shè)置幾個(gè)cronjob虱痕,如每天活著沒9天(因?yàn)楦糁?0天)再?gòu)膕ecrets-manager拿到最近更新的secrets來建立新的連接池睹耐。

  2. 連接檢測(cè)

    只使用一個(gè)用戶,如果是數(shù)據(jù)庫(kù)部翘,就在更新將到來的24h內(nèi)(48h是極端情況)在進(jìn)行正真的查詢前加一個(gè)連接檢測(cè)硝训,看看當(dāng)前的連接是否可用,如果不可用且報(bào)了auth的錯(cuò)誤新思,就從secrets-manager獲取最新的密鑰更新連接

  3. 自建lambda

    對(duì)于前面列出的已經(jīng)支持auto-rotaiton的服務(wù)aws已經(jīng)提供的對(duì)應(yīng)的lambda窖梁,我們只需要指定類型即可,但我們也可以指定自己的rotation lambda夹囚,這樣就可以在進(jìn)行rotation的時(shí)候在lambda中自己實(shí)現(xiàn)對(duì)應(yīng)用服務(wù)的通知纵刘,可以直接請(qǐng)求api活著通過使用sqs等。

  4. 手動(dòng)更改吧

    因?yàn)槟壳癱onsole上是可以指定具體時(shí)間的崔兴,那么如果對(duì)infrastructure as code沒有什么要求或者就沒有as code彰导,那可以直接在aws的console上指定具體的更新時(shí)間,比如凌晨3點(diǎn)更新敲茄,然后在應(yīng)用服務(wù)器上也定時(shí)的去獲取新的密鑰,如果是一些明顯有時(shí)間區(qū)域的應(yīng)用山析,那么可能也是一個(gè)可選的方案堰燎。

以上就是全部,個(gè)人感覺笋轨,其實(shí)secretsmanger特別是rotation這里坑還是蠻大的秆剪,如果不能為業(yè)務(wù)帶來明顯的價(jià)值赊淑,還是需要慎重考慮需不需要,如密碼的更新即便在得到了通知之后還需要考慮是要建立新的連接池還是可以支持動(dòng)態(tài)密碼仅讽,這些細(xì)節(jié)大概率都會(huì)增加系統(tǒng)復(fù)雜度陶缺。

PS:可能是一年多以來打中文最多的一次了了,發(fā)現(xiàn)水果家自帶的中文輸入法聯(lián)想整的是狗屎都不如洁灵。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饱岸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子徽千,更是在濱河造成了極大的恐慌苫费,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件双抽,死亡現(xiàn)場(chǎng)離奇詭異百框,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牍汹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門铐维,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慎菲,你說我怎么就攤上這事嫁蛇。” “怎么了钧嘶?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵棠众,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我有决,道長(zhǎng)闸拿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任书幕,我火速辦了婚禮新荤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘台汇。我一直安慰自己苛骨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布苟呐。 她就那樣靜靜地躺著痒芝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牵素。 梳的紋絲不亂的頭發(fā)上严衬,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音笆呆,去河邊找鬼请琳。 笑死粱挡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的俄精。 我是一名探鬼主播询筏,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼竖慧!你這毒婦竟也來了嫌套?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤测蘑,失蹤者是張志新(化名)和其女友劉穎灌危,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碳胳,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勇蝙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挨约。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片味混。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖诫惭,靈堂內(nèi)的尸體忽然破棺而出翁锡,到底是詐尸還是另有隱情,我是刑警寧澤夕土,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布馆衔,位于F島的核電站,受9級(jí)特大地震影響怨绣,放射性物質(zhì)發(fā)生泄漏角溃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一篮撑、第九天 我趴在偏房一處隱蔽的房頂上張望减细。 院中可真熱鬧,春花似錦赢笨、人聲如沸未蝌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萧吠。三九已至,卻和暖如春桐筏,著一層夾襖步出監(jiān)牢的瞬間怎憋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工九昧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绊袋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓铸鹰,卻偏偏與公主長(zhǎng)得像癌别,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹋笼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容