Keystone幾種token產生的方式分析_openstack

來源:互聯網
上載者:User

從Keystone的設定檔中,我們可見,Token的提供者目前支援四種。 Token Provider:UUID, PKI, PKIZ, or Fernet

結合源碼及官方文檔,我們用一個表格來闡述一下它們之間的差異。

Provider方式 產生方式|長度|加密方式 優點 缺點 UUID

uuid.uuid4().hex,32字元,沒有加密方式。
產生的Token,長度較短,使用方便。url使用方便,回收的方式,就是從後端刪除即可,實現邏輯較為清晰。 需要持久化後端儲存,每次訪問需要keystone相關服務進行認證。 PKI cms_sign_data(),使用base64 encoded進行編碼(替換不安全的字元),粗略統計過長度4602字元,使用 Cryptographic Message Syntax (CMS)進行加密(預設的方式sha256)。 使用認證及私密金鑰產生,可以線下驗證(不需要走keystone認證服務), 長度負載重,不推薦用於生產部署 :keystone-manage pki_setup ,需要使用由一個受信任的CA頒發的認證 PKIZ 同PKI,使用base64url encoding進行編碼,在此基礎上,使用壓縮機制,長度上減小了一半,並且Token使用PKIZ_開頭。 較PKI長度上縮小了很多, 長度負載較重,同上PKI Fernet MessagePacked負載資料,並使用crypto.encrypt(payload)加密,粗略統計長度183字元。使用對稱式加密,為了安全度提升,同時支援定期輪換。 設計的邏輯,引入序列化,負載格式加以控制,基於此進行加密,長度比PKI(Z)要短。 對稱式加密演算法,安全性低 接下去,從源碼上來進一步分析流程。

(1)首先,uuid,這種方式較簡單,沒有特別的加密、編碼流程,核心的產生過程,即 uuid.uuid4().hex,產生一串友好的序列。

(2)PKI的流程,首先需要使用 keystone-manage pki_setup命令產生CA及相關的令牌機制,其代碼如下所示:

    def _get_token_id(self, token_data):
        try:


            token_json = jsonutils.dumps(token_data, cls=utils.PKIEncoder)
            token_id = str(cms.cms_sign_token(token_json,
                                              CONF.signing.certfile,
                                              CONF.signing.keyfile))   #DEFAULT_TOKEN_DIGEST_ALGORITHM=sha256

其中,‘token_data’是擷取的user、role、endpoint、catlog等資訊集合,而最重要的語句是cms使用簽名產生token的過程:cms_sign_token,使用預設的sha256方式加密,處理過程使用process,進行資料的讀取、處理, 

           process = subprocess.Popen(['openssl', 'cms', '-sign',
                                 '-signer', signing_cert_file_name,
                                 '-inkey', signing_key_file_name,
                                 '-outform', 'PEM',
                                 '-nosmimecap', '-nodetach',
                                 '-nocerts', '-noattr',
 
                                 '-md', message_digest, ],
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                close_fds=True)

最後output, err = process.communicate(data) 產生Token-id,這個過程涉及到openssl相關的加密技術,再次不作詳述。我們只需清楚這個產生的大致流程。

(3)PKIZ的Token產生流程,和PKI類似,即在它的基礎上進行的壓縮,核心邏輯如下:

    def _get_token_id(self, token_data):
        try:


            token_json = jsonutils.dumps(token_data, cls=utils.PKIEncoder)
            token_id = str(cms.pkiz_sign(token_json,
                                         CONF.signing.certfile,
                                         CONF.signing.keyfile))

和PKI不同的是採用cms.pkiz_sign這個過程,進一步看這個過程,

def pkiz_sign(text,
               signing_cert_file_name,
               signing_key_file_name,
               compression_level=6,
               message_digest=DEFAULT_TOKEN_DIGEST_ALGORITHM):
     signed = cms_sign_data(text,


                            signing_cert_file_name,
                            signing_key_file_name,
                            PKIZ_CMS_FORM,
                            message_digest=message_digest)
 
     compressed = zlib.compress(signed, compression_level)
     encoded = PKIZ_PREFIX + base64.urlsafe_b64encode(   #PKIZ_PREFIX =pkiz_
         compressed).decode('utf-8')
     return encoded

在PKI原來的基礎上,引入了ZIib壓縮,並且使用pkiz_作為token的開頭。

(4)Fernet的技術,也需要首先使用命令keystone-manage fernet_setup產生必要的令牌資訊,只是它有0,1版本的區分,並且可以指定版本的個數,預設是不超過3個。

(猜測這個是為了提高安全性,和輪詢替換相關)Fernet的Token-id產生過程,和參數scope有很大的關係,它的核心代碼中,支援Project模式、Domain模式、無模式等等,處理方法略有差異,因此Fernet的Token的邏輯,與使用者的項目、域有很大的關係,Token-id的產生隨機因素降低了。我們以其中Projec的模式進行分析。

payload = FederatedProjectScopedPayload.assemble(    user_id,    methods,    project_id,    expires_at,    audit_ids,    federated_info)

versioned_payload = (version,) + payloadserialized_payload = msgpack.packb(versioned_payload)token = self.pack(serialized_payload)
從上面的代碼中,可見首先是對負載資料payload的處理,組裝過程,(應該是一個數理學家設計的。。。)
b_user_id = cls.attempt_convert_uuid_hex_to_bytes(user_id)  
             #user_id 傳進來前 u'b8aff9260dba489a831300630da4079f' ->後 UUID('b8aff926-0dba-489a-8313-00630da4079f')methods = auth_plugins.convert_method_list_to_integer(methods)  列表對應int的方法對應的是2*int(methods)b_project_id = cls.attempt_convert_uuid_hex_to_bytes(project_id)  expires_at_int = cls._convert_time_string_to_int(expires_at)   到期時間的整數形式表示b_audit_ids = list(map(provider.random_urlsafe_str_to_bytes,                                audit_ids))                 審計為列表,並用隨機的二進位產生
組裝過程返回一個列表,進一步組成帶有version的負載,然後加密crypto.encrypt(payload).rstrip('='),最後然後進行編碼處理,返回Token-id。

通過以上四種的Token產生方式分析,可見每種方式都有優缺點,如果希望少去和Keystone互動,減少認證請求頻寬,可以採用PKI、PKIZ、Fernet的方式,而這幾種方式的邏輯各有差異,涉及到加密方法的安全性,CA的權威性,這都需要進一步斟酌,uuid是keystone目前版本預設的安裝方式,其使用簡單,只是存在每次請求token都需要和keytone互動。總之,它們的存在都有自己的優跟缺。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.