VYPR
High severity7.5NVD Advisory· Published Feb 3, 2016· Updated May 6, 2026

CVE-2015-7546

CVE-2015-7546

Description

The identity service in OpenStack Identity (Keystone) before 2015.1.3 (Kilo) and 8.0.x before 8.0.2 (Liberty) and keystonemiddleware (formerly python-keystoneclient) before 1.5.4 (Kilo) and Liberty before 2.3.3 does not properly invalidate authorization tokens when using the PKI or PKIZ token providers, which allows remote authenticated users to bypass intended access restrictions and gain access to cloud resources by manipulating byte fields within a revoked token.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
keystonePyPI
>= 9.0.0.0b1, < 9.0.0.0b29.0.0.0b2
keystonemiddlewarePyPI
>= 2.4.0, < 4.1.04.1.0
keystonePyPI
>= 8.0, < 8.1.08.1.0
keystonemiddlewarePyPI
< 1.5.41.5.4
keystonemiddlewarePyPI
>= 1.6.0, < 2.3.32.3.3

Affected products

3

Patches

3
96ab58e6863c

auth_token verify revocation by audit_id

https://github.com/openstack/keystonemiddlewareBrant KnudsonDec 1, 2015via ghsa
11 files changed · +296 174
  • examples/pki/cms/auth_token_scoped.json+4 1 modified
    @@ -8,7 +8,10 @@
                     "enabled": true,
                     "description": null,
                     "name": "tenant_name1"
    -            }
    +            },
    +            "audit_ids": [
    +                "SLIXlXQUQZWUi9VJrqdXqA"
    +            ]
             },
             "serviceCatalog": [
                 {
    
  • examples/pki/cms/auth_token_scoped.pem+75 73 modified
    @@ -1,75 +1,77 @@
     -----BEGIN CMS-----
    -MIINhwYJKoZIhvcNAQcCoIINeDCCDXQCAQExCTAHBgUrDgMCGjCCC5QGCSqGSIb3
    -DQEHAaCCC4UEgguBew0KICAgICJhY2Nlc3MiOiB7DQogICAgICAgICJ0b2tlbiI6
    -IHsNCiAgICAgICAgICAgICJleHBpcmVzIjogIjIwMzgtMDEtMThUMjE6MTQ6MDda
    -IiwNCiAgICAgICAgICAgICJpZCI6ICJwbGFjZWhvbGRlciIsDQogICAgICAgICAg
    -ICAidGVuYW50Ijogew0KICAgICAgICAgICAgICAgICJpZCI6ICJ0ZW5hbnRfaWQx
    -IiwNCiAgICAgICAgICAgICAgICAiZW5hYmxlZCI6IHRydWUsDQogICAgICAgICAg
    -ICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICAgICAibmFt
    -ZSI6ICJ0ZW5hbnRfbmFtZTEiDQogICAgICAgICAgICB9DQogICAgICAgIH0sDQog
    -ICAgICAgICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAg
    -ICAgICAgICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAg
    -ICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAg
    -ICAgICAgICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6
    -ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAg
    -ICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAg
    -ICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4w
    -LjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwN
    -CiAgICAgICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEy
    -Ny4wLjAuMTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdh
    -Ig0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAg
    -ICAgICAgICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAgICAgICAg
    -ICJuYW1lIjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7
    -DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAg
    -ICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsN
    -CiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3
    -LjAuMC4xOjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv
    -biI6ICJyZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVy
    -bmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAg
    -ICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5
    -Mi92MSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s
    -DQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAg
    -ICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg
    -ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAg
    -ICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAg
    -IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8v
    -MTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2
    -NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv
    -bk9uZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAi
    -aHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBm
    -Y2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VS
    -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVl
    -OGE2MGZjZjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAg
    -ICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIs
    -DQogICAgICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0s
    -DQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5r
    -cyI6IFtdLA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAg
    -ICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVS
    -TCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAgICAgICAg
    -ICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAgICAgICAg
    -ICAgICAgICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUz
    -NTcvdjIuMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjog
    -Imh0dHA6Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAgICAgICAg
    -ICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6
    -ICJpZGVudGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUi
    -DQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0K
    -ICAgICAgICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAgICAgICAg
    -ICAgInJvbGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xlMSIsDQog
    -ICAgICAgICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAgICAgICAg
    -ICAgICJpZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMiOiBbDQog
    -ICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJy
    -b2xlMSINCiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAg
    -ICAgICAgICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAg
    -ICAgfQ0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJf
    -bmFtZTEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHKMIIBxgIBATCBpDCBnjEK
    -MAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlT
    -dW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUx
    -JTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMT
    -C1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAGFaC8Po
    -svBez6wHfGxgqtX+Zk7kFH0xu/JA7fWp8L5e1k1q+wsSII/P6rATOXR8BSPwifat
    -mKRan9kzerLeb3A5g07VphvHfVkDEVaeihi33bpt7140ELSKu/ogWQPtasjBM9Eb
    -M9pS4N5NCtZ0erE5DgX//IRfrHFdZuhIbwlmei72692PV7Q70t/rbaH8ofIrH7Rz
    -Z1Kuvj0+7tELgd52wy5YnU0e879OEj+2qUk30TvqRG9jdKxLSanmR/8dSA2eNNgO
    -oHrtXc4EmpWFbP6yVxNwK3dQ6OvU4virV1YW5+De2ApLt+IeojaVPGnDPfsRvY5x
    -t0eIwpDqkgvkRP8=
    +MIIN5QYJKoZIhvcNAQcCoIIN1jCCDdICAQExDTALBglghkgBZQMEAgEwggvqBgkq
    +hkiG9w0BBwGgggvbBIIL13sNCiAgICAiYWNjZXNzIjogew0KICAgICAgICAidG9r
    +ZW4iOiB7DQogICAgICAgICAgICAiZXhwaXJlcyI6ICIyMDM4LTAxLTE4VDIxOjE0
    +OjA3WiIsDQogICAgICAgICAgICAiaWQiOiAicGxhY2Vob2xkZXIiLA0KICAgICAg
    +ICAgICAgInRlbmFudCI6IHsNCiAgICAgICAgICAgICAgICAiaWQiOiAidGVuYW50
    +X2lkMSIsDQogICAgICAgICAgICAgICAgImVuYWJsZWQiOiB0cnVlLA0KICAgICAg
    +ICAgICAgICAgICJkZXNjcmlwdGlvbiI6IG51bGwsDQogICAgICAgICAgICAgICAg
    +Im5hbWUiOiAidGVuYW50X25hbWUxIg0KICAgICAgICAgICAgfSwNCiAgICAgICAg
    +ICAgICJhdWRpdF9pZHMiOiBbDQogICAgICAgICAgICAgICAgIlNMSVhsWFFVUVpX
    +VWk5VkpycWRYcUEiDQogICAgICAgICAgICBdDQogICAgICAgIH0sDQogICAgICAg
    +ICJzZXJ2aWNlQ2F0YWxvZyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAg
    +ICAgICAiZW5kcG9pbnRzX2xpbmtzIjogW10sDQogICAgICAgICAgICAgICAgImVu
    +ZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAg
    +ICAgICAgICAgICAgImFkbWluVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92
    +MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAg
    +ICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIsDQogICAgICAgICAg
    +ICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzEyNy4wLjAuMTo4
    +Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAg
    +ICAgICAgICAgICAgICAgICAgICJwdWJsaWNVUkwiOiAiaHR0cDovLzEyNy4wLjAu
    +MTo4Nzc2L3YxLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIg0KICAg
    +ICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgXSwNCiAgICAgICAg
    +ICAgICAgICAidHlwZSI6ICJ2b2x1bWUiLA0KICAgICAgICAgICAgICAgICJuYW1l
    +IjogInZvbHVtZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAg
    +ICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAgICAg
    +ICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAg
    +ICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAuMC4x
    +OjkyOTIvdjEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJy
    +ZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVybmFsVVJM
    +IjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAg
    +ICAgICAgICAicHVibGljVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIN
    +CiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0sDQogICAg
    +ICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAgICAgICJu
    +YW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQog
    +ICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtdLA0KICAgICAgICAg
    +ICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAg
    +ICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJodHRwOi8vMTI3LjAu
    +MC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIs
    +DQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSIs
    +DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJuYWxVUkwiOiAiaHR0cDov
    +LzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJi
    +NjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInB1YmxpY1VSTCI6ICJo
    +dHRwOi8vMTI3LjAuMC4xOjg3NzQvdjEuMS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZj
    +Zjg5YmI2NjE3YSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg
    +ICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiY29tcHV0ZSIsDQogICAg
    +ICAgICAgICAgICAgIm5hbWUiOiAibm92YSINCiAgICAgICAgICAgIH0sDQogICAg
    +ICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50c19saW5rcyI6IFtd
    +LA0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg
    +ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJhZG1pblVSTCI6ICJo
    +dHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YyLjAiLA0KICAgICAgICAgICAgICAgICAg
    +ICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiLA0KICAgICAgICAgICAgICAgICAg
    +ICAgICAgImludGVybmFsVVJMIjogImh0dHA6Ly8xMjcuMC4wLjE6MzUzNTcvdjIu
    +MCIsDQogICAgICAgICAgICAgICAgICAgICAgICAicHVibGljVVJMIjogImh0dHA6
    +Ly8xMjcuMC4wLjE6NTAwMC92Mi4wIg0KICAgICAgICAgICAgICAgICAgICB9DQog
    +ICAgICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICAgICAidHlwZSI6ICJpZGVu
    +dGl0eSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAia2V5c3RvbmUiDQogICAg
    +ICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJ1c2VyIjogew0KICAgICAg
    +ICAgICAgInVzZXJuYW1lIjogInVzZXJfbmFtZTEiLA0KICAgICAgICAgICAgInJv
    +bGVzX2xpbmtzIjogWw0KICAgICAgICAgICAgICAgICJyb2xlMSIsDQogICAgICAg
    +ICAgICAgICAgInJvbGUyIg0KICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJp
    +ZCI6ICJ1c2VyX2lkMSIsDQogICAgICAgICAgICAicm9sZXMiOiBbDQogICAgICAg
    +ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMSIN
    +CiAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAg
    +ICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICAgICAgfQ0K
    +ICAgICAgICAgICAgXSwNCiAgICAgICAgICAgICJuYW1lIjogInVzZXJfbmFtZTEi
    +DQogICAgICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgGA1UE
    +BRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5ueXZh
    +bGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAjBgkq
    +hkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1NlbGYg
    +U2lnbmVkAgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQCgtkCXRzS8
    +s7WjZCsKDhMt6q5JQIm7x6EMKCBaOABQG9EOVIAyqfoJDdjDtz9rZEPO3UVTpPkg
    +VjtA0QV97qT8bX55AcCkk7kBRDOKTtco5GOGwjMxL+GWbIwWiB7DKIP4RA6NLZtF
    +WxUbLBY+OgBSiayuHqSx+Rd08QC9oHf25wRkTNp3VFPxtAleDmASzdAoIafoS+FB
    +Po+9WuTaGdeya7S+ms4SSyXf9cdMKGv010R/aMINWUWaBrkB4wlespYLmKH/XzwS
    +pENRIdbI9XHEOYTWKqul5tucA3p21IA24ND6acl9CXHr3KeqXpRwclSZ38Kg/23T
    +92D+SowEjlGf
     -----END CMS-----
    
  • examples/pki/cms/auth_token_scoped.pkiz+1 1 modified
    @@ -1 +1 @@
    -PKIZ_eJylVst2ozgU3OsrZp_Tx4CNY5biaRFLGMx7ZyDGYMBObJ5fPwInpyedzkxmhhUIqVS36t4r_fhBH1HREPlDwrvx4wfACK1bM9CfziE6NjGBZiyd6dg1lyRxuZCgqXSSDddi6rzKKZa0cTxeaNLuRduhaA5kU1nDPR2MVkqaeo_PvX4MOFLEc5wZmfiIKvpehZeAc-XAt46RJlQoP6fe_JpFpXoD4Q4tkaRzEdexkedkGwlmocefYk24RJU1vE8OPOu293jXObUUGGb7tcXE8rkBm0HpSb9oNzmssX1ekCHmNvOg2wwBE-RhibkwCzjM4sEciOcsAjtow5KUhlxkQR5wANvJEWVtiiq9CLmiibKJUR96ySXi-G1U3lnR3ZnQ1-vA6z6wACON_8MCjDR-shDZoOwuAevubGlick7WVmtkqwbbaD5tIC06I0_nZAiaJFcaQHIrI2UwhKWeB4MzEBmzoX08klwsAy5YGJ6ekTzoCKdkB5e5UlDm2ReLUVxUhQ2I1u6NOjH-KKLSaiOuqJM1OURaUe_vVka-Txeu77a9uVZFmloHnJOBf2vbL3rxAOenfhTsvzoBvkL-CPy1uOCjuqfesNGo7mfByuIWeEkxAZZuHa7FZmQEYla40pfXuKfI6i057NqU1gOlyb4t5JukVL5McfBNscbkYqbkot7_1XrwT96PO8elW-09ob57_yb0SahH-wGNc6RUxCV_jNTvZKA5alTj3YojGuJAmFMyJcmJjRk8uIWhKRzWwjzMUz4oEUdyZR7cE61NPJ3qRb5VTL-N93fhgr_N9ZI0kS-yifa50fhcd4nK2wAmO1hW2Ei0fY060K400eNcPp5bzXsWfpXu4BsWDlQflvQCh7NF-2vKjy7svtt9fgcOPqN_t6k4LZZhA5Ic0QFd8HfjYouPtTcNPKug8V6S9elLAUctwCjg2-KGCjdlG62F4nktXmgGTpNQjlo8pDcsKzdsHx2cK0tsm0ssJ3twp013K9U6GSnTzkN3O9IwinD6tvrEc0Z7fxbY-3xVqME4iO-Zdgp9ksdl0SbaW1PReDbS2vHfJbzrwYzgNIzD3jM7VDH3Wnj72dI-l4fesYk0WhuZLoyxJz492rI7s7gUrnSTD_0SUE_pAue9pY3vPSqYXyi7A7X1MDVV-71CRzCcgRHlQwN5B6w-deKenp8Fzt4dm0DvGny1C41zsnQKoxAuoUzrxWcFHCCxp8c8jAMJ0PO_Tfdmm4aLTsohElPiitCxoe100gD1-3dgw8K1sXltJTOQXdNESqvLpq3sABahBllHETusO3O3jqqCoylcYAu1CpwmPyltsY01t3bmFr07XDvFhts78NUGknIrnn3C0Fqgdjotav96WzmJ6jF8Df1iSDTawhyxGYHiO1AdzfUKYMtslXTaSVbamx16XYlUcgkpYEgjUj5cbyAR09PL8ZRpQsuINHwVQLij9yBp74o5-3C9beMjRm4RGubu5K2F9HGJocPh_HJ7OM-zk36Nb-eHw2sxnGZ74rvrAqi2wSpx1jJyNWd7CHM1LftoqJiSh-nGUy32Js_OzhI1jmuXPJJmF9hh5aytDpquHbdgGGbIvIVPr71BcFdDy7fk2ZFJ92m33szIIMlu-IIEf-UzJFJOwolZRZ1hz-ONETD7_AwstzFmO7fpltxy63KH5wd0qXbBIt7HrOs-YWgF-_PT7CF9KnouPykraZg9YN1WOdW_7O0ckPm5UMNs268OL8QpD24qFNvu8eHFEjtI2uct79Qmn3P8cWWacap2kXw1ZCHP4Gzj16QE2-r1YrVQqwweOk_ybmMdDF83-GVNIJjuogqRf95L_wRcTpJ3
    \ No newline at end of file
    +PKIZ_eJylVkuXojgY3edXzL5OnwLUKlnMgrdBwAJDgOx4KK-gVimC_PoJWFVdM93z6DNuNEFu7nfv98i3b-wjawZ0flPs7bj4BmwIV8s8MtdHAotr6khuqhzZ3nxQFFlcKpKr9SqSLDmneVHnMnFtTcq1Ls_DmZzXr6CoS0PsOFnujJxtHmUI9cXqXEaBU5HQGWB1zHc3k0uEC01K-ATZMxIWXRyaNL3BJwAVeLNVe24hqbeQNscq7DeVxm0qaRaU8AwV80QU9qJidomhVyQoronh0fT-jAMkWBTJwS03pfwMG9xGgXkmwbTm0gOmliKV8bSWyswYny-4UKC1vZ0AWhAFPB1pwoNHk0ZvM11sx733P9QsjCptaJcZ9DqFYCz4xOjFETgKcQ3i0NvHgTfFGtxMhDQaJXrhYazHmMenDSbr9KDXwUqXIeWnF1MB37KGVsR3CpAZ-jkR0pFywsRiLLwuEWibreyPvYIY_CmheIvuWhyzlddtyuXVRnAGrEpqbWXOhMtnzhBds0q7OpVXOk00kMasosEfHNXmCSoKp5KbSIjmm8AsnSrqHUErwUSpwYc4ENu7FiYlAou3Flty1-GUMH3Shomt_8gCjDT-Dwsw0phYrHCZGLTC2LQnJk3BZSvpybote7tKxwM6q9KeNmo6c0pRsLdLwTGgAEjFzmmcykE2Zw-YbgxNsA1SkSpfRA0UnEqbRVtTDLddPuYJWcnXmOVCyotn9v0GxnSE-iUbWWQr2rG4xxiFROj5JPAndiw_Ln_d3zPA0TXwq7Z916u-bRC8AiZY-X-cAH-H_An8L-KCT3URXNiTun8v2M_0AhO9QD-8U20_i6vJzqzyKsIALeVeqZ-AdyC2p9cgCWj7n7xXRnbz3hoiLqpIYwukjASbB_bgDk7gzyMUdaRxmo1Ky6hij1BWwLL7Lmg5CXcjQXZKhMVL0twtBiMlEo7Ue-zX3dQ44pXHperxag3azbmNLJjA6Dh3hpSzZlFvfUl18F8q7p_cAL8S78_CBZ_xHvjJHtYj69QQx8QZQqE_Jc3l3q14bmqiu1B-d8m5JqHMs470Q763yYwwQPbC2MK_AE5As7Hlexem3aQZ-AfRBlahvHNj4ZTz7ieObEdHwFdLfsGRT3DwHV3mo6Y_Rfy_VaHf2arEagWytSmCX8n7aUqx4cJmBLf7YbA0F7oLHTYDF_TDkSx0xhE2zcPp91jOrJlMU2pcU_EO8D6Fbqzb0D8zOLM-IZ4J-ugZ429Y3lnTejwYwAMemHBsOrn9u9JseOJPy77YOx1gf1bnnc1k4wfyHnN_Lul38AmEsdiHvGhHUB4qRZHS43h36EAeu11O5r1SSVDOHSxLPpKQ3yuDZN7XEZIoRrZ77hQ3UrHrQq0zVRdpW1uWDCDxvib3tunPcJscqMBygNoe7DRp-vNa6-hLypT3Z14RCedeQ9LLHfiMFO1CwYfy9tbvYPf1qlPLekHeSEiHzGDN1ZevI1B6B2Lpbh5sz-2Alk8nqVp3QSToG6g7J8IACYtI-8ndSHW_HqLJQHYlLc81aX3lauEoClh6VuT6CVmW_Xx4cUKMVpistrF-8znERbl2fHvMwv1Zg7ipXuENxJolYFGlM8EwxIGkw0pI51zZPri711NwFfOy9-h2eDMzXGe6HAtPSqjDtyZSZq0lXBUA-dVBNQ9FszxyDqe-1DG0sq2P0nb_-vCoLDptv3s43RpcnC1-vVPWh6J_uR7D1-xVklHsgVJt1t5DSq3mbKql9HradSuMTCoWQ_HywKdLk7-01l5nbWlbqI8WXjxrwgYhdFwe0MF9AUVO9lb9XD9JQ2Ku-TjaCYawm8_np5i1w2pmP9qSdKH5rttzT12SxPlSXOs3xXe0U6N6BnD2jNsSSlK1ffBnwirm-se3_a7NcLsk-e-_g-lCqznq98vtH9MPoOI=
    \ No newline at end of file
    
  • examples/pki/cms/auth_v3_token_scoped.json+3 0 modified
    @@ -1,5 +1,8 @@
     {
         "token": {
    +        "audit_ids": [
    +            "SLIXlXQUQZWUi9VJrqdXqA"
    +        ],
             "methods": [
                 "password"
             ],
    
  • examples/pki/cms/auth_v3_token_scoped.pem+96 94 modified
    @@ -1,98 +1,100 @@
     -----BEGIN CMS-----
    -MIIR5gYJKoZIhvcNAQcCoIIR1zCCEdMCAQExCTAHBgUrDgMCGjCCD/MGCSqGSIb3
    -DQEHAaCCD+QEgg/gew0KICAgICJ0b2tlbiI6IHsNCiAgICAgICAgIm1ldGhvZHMi
    -OiBbDQogICAgICAgICAgICAicGFzc3dvcmQiDQogICAgICAgIF0sDQogICAgICAg
    -ICJyb2xlcyI6IFsNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAibmFt
    -ZSI6ICJyb2xlMSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAg
    -ICAgICAgICAgICAgIm5hbWUiOiAicm9sZTIiDQogICAgICAgICAgICB9DQogICAg
    -ICAgIF0sDQogICAgICAgICJleHBpcmVzX2F0IjogIjIwMzgtMDEtMThUMjE6MTQ6
    -MDdaIiwNCiAgICAgICAgInByb2plY3QiOiB7DQogICAgICAgICAgICAiaWQiOiAi
    -dGVuYW50X2lkMSIsDQogICAgICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAg
    -ICAgICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFt
    -ZSI6ICJkb21haW5fbmFtZTEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAg
    -ImVuYWJsZWQiOiB0cnVlLA0KICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVs
    -bCwNCiAgICAgICAgICAgICJuYW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAg
    -fSwNCiAgICAgICAgImNhdGFsb2ciOiBbDQogICAgICAgICAgICB7DQogICAgICAg
    -ICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0K
    -ICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQog
    -ICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6
    -ODc3Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAg
    -ICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAg
    -ICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAg
    -ICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJpbnRlcm5hbCIsDQogICAg
    -ICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3
    -Ni92MS82NGI2ZjNmYmNjNTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAg
    -ICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAg
    -ICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAg
    -ICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAg
    -ICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEv
    -NjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAg
    -ICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAg
    -ICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0
    -eXBlIjogInZvbHVtZSIsDQogICAgICAgICAgICAgICAgIm5hbWUiOiAidm9sdW1l
    -Ig0KICAgICAgICAgICAgfSwNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAg
    -ICAiZW5kcG9pbnRzIjogWw0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAg
    -ICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAg
    -ICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3Yx
    -IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25l
    -Ig0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7
    -DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFs
    -IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4w
    -LjAuMTo5MjkyL3YxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24i
    -OiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAg
    -ICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNl
    -IjogInB1YmxpYyIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0
    -dHA6Ly8xMjcuMC4wLjE6OTI5Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAg
    -ICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0K
    -ICAgICAgICAgICAgICAgIF0sDQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1h
    -Z2UiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAg
    -ICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50
    +MIISOAYJKoZIhvcNAQcCoIISKTCCEiUCAQExDTALBglghkgBZQMEAgEwghA9Bgkq
    +hkiG9w0BBwGgghAuBIIQKnsNCiAgICAidG9rZW4iOiB7DQogICAgICAgICJhdWRp
    +dF9pZHMiOiBbDQogICAgICAgICAgICAiU0xJWGxYUVVRWldVaTlWSnJxZFhxQSIN
    +CiAgICAgICAgXSwNCiAgICAgICAgIm1ldGhvZHMiOiBbDQogICAgICAgICAgICAi
    +cGFzc3dvcmQiDQogICAgICAgIF0sDQogICAgICAgICJyb2xlcyI6IFsNCiAgICAg
    +ICAgICAgIHsNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJyb2xlMSINCiAgICAg
    +ICAgICAgIH0sDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgIm5hbWUi
    +OiAicm9sZTIiDQogICAgICAgICAgICB9DQogICAgICAgIF0sDQogICAgICAgICJl
    +eHBpcmVzX2F0IjogIjIwMzgtMDEtMThUMjE6MTQ6MDdaIiwNCiAgICAgICAgInBy
    +b2plY3QiOiB7DQogICAgICAgICAgICAiaWQiOiAidGVuYW50X2lkMSIsDQogICAg
    +ICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAgICAgICAgICJpZCI6ICJkb21h
    +aW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFtZSI6ICJkb21haW5fbmFtZTEi
    +DQogICAgICAgICAgICB9LA0KICAgICAgICAgICAgImVuYWJsZWQiOiB0cnVlLA0K
    +ICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogbnVsbCwNCiAgICAgICAgICAgICJu
    +YW1lIjogInRlbmFudF9uYW1lMSINCiAgICAgICAgfSwNCiAgICAgICAgImNhdGFs
    +b2ciOiBbDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50
     cyI6IFsNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAg
     ICAgICAgImludGVyZmFjZSI6ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAg
    -ICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2Zi
    -Y2M1MzQzNWU4YTYwZmNmODliYjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAg
    -ICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9
    -LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAg
    -ICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAg
    -ICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJj
    -YzUzNDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAg
    -ICAgInJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0s
    -DQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAg
    -ICJpbnRlcmZhY2UiOiAicHVibGljIiwNCiAgICAgICAgICAgICAgICAgICAgICAg
    -ICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUz
    -NDM1ZThhNjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAg
    -InJlZ2lvbiI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAg
    -ICAgICAgICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogImNvbXB1
    -dGUiLA0KICAgICAgICAgICAgICAgICJuYW1lIjogIm5vdmEiDQogICAgICAgICAg
    -ICB9LA0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMi
    -OiBbDQogICAgICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAg
    -ICAgICJpbnRlcmZhY2UiOiAiYWRtaW4iLA0KICAgICAgICAgICAgICAgICAgICAg
    -ICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAg
    -ICAgICAgICAgICAgICAgICJyZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAgICAg
    -ICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAg
    -ICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAg
    -ICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTozNTM1Ny92
    -MyIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9u
    -ZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAg
    -ew0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMi
    -LA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAu
    -MC4xOjUwMDAvdjMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6
    -ICJSZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAg
    -ICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogImlkZW50aXR5IiwNCiAg
    -ICAgICAgICAgICAgICAibmFtZSI6ICJrZXlzdG9uZSINCiAgICAgICAgICAgIH0N
    -CiAgICAgICAgXSwNCiAgICAgICAgInVzZXIiOiB7DQogICAgICAgICAgICAiZG9t
    -YWluIjogew0KICAgICAgICAgICAgICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAg
    -ICAgICAgICAgICAgICAibmFtZSI6ICJkb21haW5fbmFtZTEiDQogICAgICAgICAg
    -ICB9LA0KICAgICAgICAgICAgIm5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAg
    -ICAgICAiaWQiOiAidXNlcl9pZDEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHK
    -MIIBxgIBATCBpDCBnjEKMAgGA1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
    -AkNBMRIwEAYDVQQHEwlTdW5ueXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8G
    -A1UECxMIS2V5c3RvbmUxJTAjBgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFj
    -ay5vcmcxFDASBgNVBAMTC1NlbGYgU2lnbmVkAgERMAcGBSsOAwIaMA0GCSqGSIb3
    -DQEBAQUABIIBAMq7ffe3ft88hD0EXJfWqkoEGcnal6NmTuLAiCOeQjDxR5TEIx0x
    -HanKHWAG7Ko/97KgKAAFwOq3hhnbbKbKq7Z3brUNPXNRwBd3RusUrsLQOWwwKAsF
    -acD8a4XXx6oC8dTsuFivDtMNb1JvBRIWcZXznOtn/bkFcvVhOQ+Af93c9xPBUpMq
    -1667DbVKWRJEsMrcf5r7wYRQBtAKZU3CAjbNDighdTJWwF7TIWZycnF3OHYmu5J2
    -wvcuB8ex+xRvf1lw1qnb3lC43A4M1KqhnHPpWUrpmAFnzAcYwc7ts2iCqD/UwVBP
    -YcXU8kk8bY6leNJKR9xjHcIfW8SnREZVbXA=
    +ICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNj
    +NTM0MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAg
    +ICAicmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwN
    +CiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAg
    +ImludGVyZmFjZSI6ICJpbnRlcm5hbCIsDQogICAgICAgICAgICAgICAgICAgICAg
    +ICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6ODc3Ni92MS82NGI2ZjNmYmNjNTM0
    +MzVlOGE2MGZjZjg5YmI2NjE3YSIsDQogICAgICAgICAgICAgICAgICAgICAgICAi
    +cmVnaW9uIjogInJlZ2lvbk9uZSINCiAgICAgICAgICAgICAgICAgICAgfSwNCiAg
    +ICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImlu
    +dGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVy
    +bCI6ICJodHRwOi8vMTI3LjAuMC4xOjg3NzYvdjEvNjRiNmYzZmJjYzUzNDM1ZThh
    +NjBmY2Y4OWJiNjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lv
    +biI6ICJyZWdpb25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAg
    +ICAgICAgICBdLA0KICAgICAgICAgICAgICAgICJ0eXBlIjogInZvbHVtZSIsDQog
    +ICAgICAgICAgICAgICAgIm5hbWUiOiAidm9sdW1lIg0KICAgICAgICAgICAgfSwN
    +CiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAiZW5kcG9pbnRzIjogWw0K
    +ICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAi
    +aW50ZXJmYWNlIjogImFkbWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1
    +cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAgICAgICAgICAgICAg
    +ICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAgICAgICAgICAgICAg
    +ICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAg
    +ICAgICAgICAiaW50ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAg
    +ICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEyNy4wLjAuMTo5MjkyL3YxIiwNCiAg
    +ICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVnaW9uT25lIg0KICAg
    +ICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAgICAgICB7DQogICAg
    +ICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogInB1YmxpYyIsDQogICAg
    +ICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6Ly8xMjcuMC4wLjE6OTI5
    +Mi92MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAicmVnaW9uIjogInJlZ2lv
    +bk9uZSINCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIF0s
    +DQogICAgICAgICAgICAgICAgInR5cGUiOiAiaW1hZ2UiLA0KICAgICAgICAgICAg
    +ICAgICJuYW1lIjogImdsYW5jZSINCiAgICAgICAgICAgIH0sDQogICAgICAgICAg
    +ICB7DQogICAgICAgICAgICAgICAgImVuZHBvaW50cyI6IFsNCiAgICAgICAgICAg
    +ICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgImludGVyZmFjZSI6
    +ICJhZG1pbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAidXJsIjogImh0dHA6
    +Ly8xMjcuMC4wLjE6ODc3NC92MS4xLzY0YjZmM2ZiY2M1MzQzNWU4YTYwZmNmODli
    +YjY2MTdhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJyZWdpb24iOiAicmVn
    +aW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAgICAgICAgICAgICAg
    +ICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50ZXJmYWNlIjogImlu
    +dGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDov
    +LzEyNy4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJi
    +NjYxN2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdp
    +b25PbmUiDQogICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAg
    +ICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAicHVi
    +bGljIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1cmwiOiAiaHR0cDovLzEy
    +Ny4wLjAuMTo4Nzc0L3YxLjEvNjRiNmYzZmJjYzUzNDM1ZThhNjBmY2Y4OWJiNjYx
    +N2EiLA0KICAgICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJyZWdpb25P
    +bmUiDQogICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0K
    +ICAgICAgICAgICAgICAgICJ0eXBlIjogImNvbXB1dGUiLA0KICAgICAgICAgICAg
    +ICAgICJuYW1lIjogIm5vdmEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAg
    +ew0KICAgICAgICAgICAgICAgICJlbmRwb2ludHMiOiBbDQogICAgICAgICAgICAg
    +ICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICJpbnRlcmZhY2UiOiAi
    +YWRtaW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgInVybCI6ICJodHRwOi8v
    +MTI3LjAuMC4xOjM1MzU3L3YzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJy
    +ZWdpb24iOiAiUmVnaW9uT25lIg0KICAgICAgICAgICAgICAgICAgICB9LA0KICAg
    +ICAgICAgICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgICAgICAgICAiaW50
    +ZXJmYWNlIjogImludGVybmFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJ1
    +cmwiOiAiaHR0cDovLzEyNy4wLjAuMTozNTM1Ny92MyIsDQogICAgICAgICAgICAg
    +ICAgICAgICAgICAicmVnaW9uIjogIlJlZ2lvbk9uZSINCiAgICAgICAgICAgICAg
    +ICAgICAgfSwNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAg
    +ICAgICAgICAgImludGVyZmFjZSI6ICJwdWJsaWMiLA0KICAgICAgICAgICAgICAg
    +ICAgICAgICAgInVybCI6ICJodHRwOi8vMTI3LjAuMC4xOjUwMDAvdjMiLA0KICAg
    +ICAgICAgICAgICAgICAgICAgICAgInJlZ2lvbiI6ICJSZWdpb25PbmUiDQogICAg
    +ICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBdLA0KICAgICAgICAg
    +ICAgICAgICJ0eXBlIjogImlkZW50aXR5IiwNCiAgICAgICAgICAgICAgICAibmFt
    +ZSI6ICJrZXlzdG9uZSINCiAgICAgICAgICAgIH0NCiAgICAgICAgXSwNCiAgICAg
    +ICAgInVzZXIiOiB7DQogICAgICAgICAgICAiZG9tYWluIjogew0KICAgICAgICAg
    +ICAgICAgICJpZCI6ICJkb21haW5faWQxIiwNCiAgICAgICAgICAgICAgICAibmFt
    +ZSI6ICJkb21haW5fbmFtZTEiDQogICAgICAgICAgICB9LA0KICAgICAgICAgICAg
    +Im5hbWUiOiAidXNlcl9uYW1lMSIsDQogICAgICAgICAgICAiaWQiOiAidXNlcl9p
    +ZDEiDQogICAgICAgIH0NCiAgICB9DQp9DQoxggHOMIIBygIBATCBpDCBnjEKMAgG
    +A1UEBRMBNTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTdW5u
    +eXZhbGUxEjAQBgNVBAoTCU9wZW5TdGFjazERMA8GA1UECxMIS2V5c3RvbmUxJTAj
    +BgkqhkiG9w0BCQEWFmtleXN0b25lQG9wZW5zdGFjay5vcmcxFDASBgNVBAMTC1Nl
    +bGYgU2lnbmVkAgERMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQBBvzoh
    +0iSPMQhuRCAtTG3cPhyewvf554MPjbGQnu8mYmmfyxl7gMmWkTAmyckAsSv4mS6/
    +4SQj9WCn4T1lFkhUz7WWjCwt6fWWp3mzF8Nl/kMsJKDwlxDGbPzsyewXIUsw11sz
    +q/Qxs7qGxQ1vYWnaWQ3hC3oZw7cOswKRJicdP439iVPvfqR9CDbK55sPP+ewZRgQ
    +YJ3Uc/xDizxepudFJj9+VHKceA37/sVK0ataNe2uHLHwVBYPwOppMckP169QBw8x
    +QYh9h+kcOAyZ5psiUzCpLKnlMiYDrVcTGxnTeiVHxKXxj/MERNhR1Y4lEr0ZHJ+p
    +Y6p3FBP2VUCefaRh
     -----END CMS-----
    
  • examples/pki/cms/auth_v3_token_scoped.pkiz+1 1 modified
    @@ -1 +1 @@
    -PKIZ_eJy9V8lyo0gQvddXzN3RYUCgNoc-FItYTCGBEEvdWCwWscjWwvL1UyDJ3W577J6YiFGEDlUFmS_zvcxKvn0jP0FWNPMvEa3HxTeANE1X2kB_bLCWnWMTWrHYkD1JEkXRSkVoyZ3oQFVINy9SikSlEEWhTxVx_aystWgGJEtWYUg2u52cprH71OtUxBzLKNfmmnrIY1U_h5VbJOJljRX-GHjlSSualDx7AoFHl-NCq-xz5C32Ucmfxj201g6aqO_x-KKo7yKGzkKP24ae1Wk1NZ6VUbXIQaS4u9FAouo0XrfEEJdF3iZf5jBPFJcY4yifmfY6LR_P7TJmzD70BSr0-BMYX45q9xCJ42E5GdNqe7R-Shb8Hktyvh0N1_qZOBvGc292yMn5Ea-1OSBQ-ojpCGSdN0Th-68I4oo_YEfLt-4E-Yh9u4kY-2Kk19vANweQMHyPRT0xRJhjP2tDXy9jms-mpIlajyTEGg7sDEdmXUnrloVMLQs48_IpRwUIfDuLFL7-HRo5ZAgyekQzGfe4Xazw-6i2X8NIfP0ALgxkVKLCudE_dKiIT0hkW6OQ50spnpk5z6D1A2MqGoMLswoqszAdRKHBLZeKzACk4AIXKRdUGmMW8iy40kc8lXGFs4C55CPw7GPosROauHLrkYHROSDZLTFTnqMdf8K3RNZuH134bxLVbpf5wxk52swo4IiO5CGdmUNwTgr5DMzCzgmwAVd6EQybwZQQjZ0sMwuhCpiAXXp6bhZBZzLy5J2IicK-XgWeWV4QVOWJCKYnyTtMQrkhyicEPfaSfcRwq6jaTHog8qXjqp3CClWbArHUnI1B7s1-TByB6DSsOcSMMQs6YwiooMAVYnAeMIhGgzWY3oYNnKDFlVktpTIHQUGOnCS7yPSCBleL4kplm3j6IfTQu-TdkIJb8vxJrjYXK9c6ICpMxkIbC0d9o486UhankZ3RKPgngXyqD0fj0KQP7QD-DecfUQ6-5nzXE48j5_8fjRwiXkca_4QZ8FmMvzMTenSGmVckU-u7ViN3Tir507L9J1bAa9mKIy3sH6nvV_GBD2LMsELvo0vHuSaRvba4S7gOw70KDHwpmi_Qgc_gfYDuKjrSeMULQvAVxK8Qgv-SwBEh-Lfl-7tGwE0kAcMfY9Wl8AcXTMi4XDwjd2f1vsWDPy1hNPZLJyZFhd4UFbhVlVYtdtF4bb8vqPVnBQXGivqgoIg3RJs9SW7_8T1xRTDOB-37hJV_fleAn41j0yIJvovxNcRaoIOq2wf9W4mDEc7mjYDo6aZO1LK9qQ-TQSNRSurplT53wL5GQhlb2m20uc5Ev3Tf17Fm2nNuLc2acnCblYDPlLvLcAF_fZmOGbd_O9rcppfRu36dlWgebB1FhHHTpqmqwFQWkKbsyP8JWU0rwkByLWshtzKNrEMrWtNakVvd3QyygeBOAZDeyKKARIuSO7mAlpCargBjR3RNOqo4LiHNlsBfIwEq07MZ0p2ZUEalSZEEvwBky63UTpYNuc0M7JdDohD6HLlEInodKMk8qUM78H7K2oURMQSi-mLJqMisNMgbJGiTJ9ghY8O4B5wLTuglJ-xZIiTOhDZYPLasBLOmlaxABz9HXFkQLEimVRnmJ3OlLmcvbKSdqMYrmzCrm95WXJ12CpbiH4Ln1O5ZzC2aZ6DndyU-zU7DXS1QL_Ndjdd-JsAIqbs9v3To5N5fB9zLshOf-uql6beRHX3H4Xy_hxWW6AqsHh-d7_NktVXtxxXTR2yhoe3cWAcs_bxqnxTBqRUha-onmROWuZpIXC05Em0v1vaB1bI50P2ZKjyrfXi33B4XFO47K4lXsKyFx7vW2Id3ZyKK9OUQMH7ztHPNY-vcQ38ZZliW5ORlDQYlpPYnVmg1NNNgWvIzt33g7oXy0LVwkMU8rNSu3g6ORWFa9GAxHL1NWqSxkdqqeL4HK0GEBs73RVma-_uGClnlMehWZR49Gdvvq8UiiqvZ1jZ0-OMHmD4xZFP6-bnxN6RCLsw=
    \ No newline at end of file
    +PKIZ_eJy9V0tzozoT3etX3H1qKoBNEhbfgpexMJKNjXloZyDmJWwnNs9f_wnsSWYyuXUzc6uuq7yQQN2n-_RpNd--sZ-iGxD_paLNsPgGEISmIwfm4khgWkdYtiP1yPZWjqqqTqHKtt5qjmwpCU3SIlGIjXQ50ZskiddKUryAtMgMqeEUpTEStqkqEM5Xh3MWG9Ir8abZMlMeYcnT2EhrMkfDOoQHJY0meBJOzAJAyp2hanah0NKogw9wdmEHxDT0tuxlOYtK6UwcPdtvmuS5M6vA4ynMjwk8mHVobDsAD3xsqXJG_LTZ-SaNeCmNVWZIhR3S0NRy5NZy9KmrwXaZ69wylydeBgenDTP-AoiHucEis16EAp_u3mDTYvRUruvQm51CKp2IpmeDs7CcXchmcMJCuB4S9-PmDSosXQbVPBPPHoxx0cGlw8HduJZZfobnIucLtABoM8L5IbY1ZcaqeCaNe7fnBfFxHpW0iQ1ahxnzboh8aLQSGCwHwowLvLYmb0l0KzJXaoaMe08srZjnjpSz_AY_JQZ_AuE1IXxUNiO83XzNRdqxtnq9w920sXK5Qs5xivtIsCZBa_UBF-SkRAJhjhEPUG_32NtOAydoSInLpUazIGePnDiFWTPQRYlwg83oJl58CgVxFZbbMV-AZf8UsrijkqSBcOV-gE78IS_NmPXYN89XRlIunssPVvfUojyqkDptgJXrD0uN1VUmCWjzJGADCiTHZVDiHDuIQ71Ll4YuIIPkJE_EoIQCzvVJcE1uB66Qpreqcw87T6ocQaTwwCp0fv6Opgw8fGNJ4YOyPQXdNXfgT5P3PXfgj5Lnjvrhnn2FgissUodzdyjPD0X1fd-ULFX5tD7A3xXIF-tDBCgvuiHGr3D-GeXgdzgfKXegiEbK_yMaxX8KEXxGzTUEegm8mI4Hf2hxRGjTsMRvCFkIYhEZ0pCcfjjoTT6BXc6K0KPVFYXbhWPLM4_xfN2AZfZUIwdORsjqlPW9ZIJ7u45zvfqKNsBHcfxuUt8KibWx82cQ_wkh-F35fkQIfpf3j7SDT-TLjfLN9Rrn64xh60lp5kG_7bGGeOKkKc6VMhCC6dIzM4DzoMXC9cL4nrTb1XUtmkKqBjX6w31xWIuRca2HQJAu0dzlwC8SLsU6Lt_uQnZHrJtQYIm-XawfBQVGa976MlxpXxETGkJxIsYCGt8HP8GmP8O-NpFf-sUNAStvFZ7BF5oG84h43DEJd79SCbZ_IOEfHYJPPPJIkxtGZf-JhDcfmyv4IOGCqZPb-Wvxo4x3gitGEzYrvEufjwS3A_9muBjOgF-Hi3evsY9pRH-aE07kKrTR-23AGOhiteC7BYO-33m3xtKZjqPTIJyla9ed7VzePS1dsogOs8KbzxRIeWnvGCqQoymb-eYLNvspCBoF-z8j-9iocqC5tj3TG51H9rlR7XFt6I3pbnvdQnJhyPxWB6qCVJvTWz2XbSXBriJHjupiPixFMWY9goW2QYo8vqymyHQmCg0pZhMNfkVrvQFaM1q29Ca1iE97NmBW7BBFKjLUzYuxgeFEs3VTXgfeOxOuHA6GDpgDgyWrlDrS61ukwNGT3CJrK7hnkinOzosrNq2pMvOmNoEZQAJlb6spMlSQzBngBy-KbG9lNuoqsl45jyd9AeeC-HheWe3ZcDV83l82hJcKyxTugoXTmR29W7ggfMi9NIj3U057PbLunu_O-6Pf76PznSIHxJRq4e7OOIWL7KTwPgcP9f2rd7_dRKUwebBCDmgngUi2KFhknc5gFhThttK4Je6NbWFO4GIz0T3rsfJW4mql2yo1yqqtlZnzjLO21O874K2f7p-3F08ISRVMDf_iXbz5PD_K8sTuT0er8oTnKn5NWsdHyHVR99DQbfas-vv01XjSVsATVN47Wg1furyTLmYXI0p8ob7Xl6tjv6sXjplX6K40Nz4WV013XF_UIgmX3fSurGfTwwJ0j4vLEa_um-eE7-4VWqYvq8eX-zbZTFYPl2htaOZRdlYzh4P_A-M3io619--V_wMk2UFA
    \ No newline at end of file
    
  • keystonemiddleware/auth_token/__init__.py+12 0 modified
    @@ -880,6 +880,18 @@ def _validate_offline(self, token, token_hashes):
                                      'fallback to online validation.'))
             else:
                 data = jsonutils.loads(verified)
    +
    +            audit_ids = None
    +            if 'access' in data:
    +                # It's a v2 token.
    +                audit_ids = data['access']['token'].get('audit_ids')
    +            else:
    +                # It's a v3 token
    +                audit_ids = data['token'].get('audit_ids')
    +
    +            if audit_ids:
    +                self._revocations.check_by_audit_id(audit_ids)
    +
                 return data
     
         def _validate_token(self, auth_ref):
    
  • keystonemiddleware/auth_token/_revocations.py+22 0 modified
    @@ -104,3 +104,25 @@ def check(self, token_ids):
             if self._any_revoked(token_ids):
                 self._log.debug('Token is marked as having been revoked')
                 raise exc.InvalidToken(_('Token has been revoked'))
    +
    +    def check_by_audit_id(self, audit_ids):
    +        """Check whether the audit_id appears in the revocation list.
    +
    +        :raises keystonemiddleware.auth_token._exceptions.InvalidToken:
    +            if the audit ID(s) appear in the revocation list.
    +
    +        """
    +        revoked_tokens = self._list.get('revoked', None)
    +        if not revoked_tokens:
    +            # There's no revoked tokens, so nothing to do.
    +            return
    +
    +        # The audit_id may not be present in the revocation events because
    +        # earlier versions of the identity server didn't provide them.
    +        revoked_ids = set(
    +            x['audit_id'] for x in revoked_tokens if 'audit_id' in x)
    +        for audit_id in audit_ids:
    +            if audit_id in revoked_ids:
    +                self._log.debug(
    +                    'Token is marked as having been revoked by audit id')
    +                raise exc.InvalidToken(_('Token has been revoked'))
    
  • keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py+24 0 modified
    @@ -768,6 +768,30 @@ def test_revoked_hashed_pki_token(self):
         def test_revoked_hashed_pkiz_token(self):
             self._test_revoked_hashed_token('signed_token_scoped_pkiz')
     
    +    def test_revoked_pki_token_by_audit_id(self):
    +        # When the audit ID is in the revocation list, the token is invalid.
    +        self.set_middleware()
    +        token = self.token_dict['signed_token_scoped']
    +
    +        # Put the token audit ID in the revocation list,
    +        # the entry will have a false token ID so the token ID doesn't match.
    +        fake_token_id = uuid.uuid4().hex
    +        # The audit_id value is in examples/pki/cms/auth_*_token_scoped.json.
    +        audit_id = 'SLIXlXQUQZWUi9VJrqdXqA'
    +        revocation_list_data = {
    +            'revoked': [
    +                {
    +                    'id': fake_token_id,
    +                    'audit_id': audit_id
    +                },
    +            ]
    +        }
    +        self.middleware._revocations._list = jsonutils.dumps(
    +            revocation_list_data)
    +
    +        self.call_middleware(headers={'X-Auth-Token': token},
    +                             expected_status=401)
    +
         def get_revocation_list_json(self, token_ids=None, mode=None):
             if token_ids is None:
                 key = 'revoked_token_hash' + (('_' + mode) if mode else '')
    
  • keystonemiddleware/tests/unit/auth_token/test_revocations.py+43 4 modified
    @@ -27,22 +27,24 @@
     
     class RevocationsTests(utils.BaseTestCase):
     
    -    def _check_with_list(self, revoked_list, token_ids):
    +    def _setup_revocations(self, revoked_list):
             directory_name = '/tmp/%s' % uuid.uuid4().hex
             signing_directory = _signing_dir.SigningDirectory(directory_name)
             self.addCleanup(shutil.rmtree, directory_name)
     
             identity_server = mock.Mock()
     
    -        verify_result_obj = {
    -            'revoked': list({'id': r} for r in revoked_list)
    -        }
    +        verify_result_obj = {'revoked': revoked_list}
             cms_verify = mock.Mock(return_value=json.dumps(verify_result_obj))
     
             revocations = _revocations.Revocations(
                 timeout=datetime.timedelta(1), signing_directory=signing_directory,
                 identity_server=identity_server, cms_verify=cms_verify)
    +        return revocations
     
    +    def _check_with_list(self, revoked_list, token_ids):
    +        revoked_list = list({'id': r} for r in revoked_list)
    +        revocations = self._setup_revocations(revoked_list)
             revocations.check(token_ids)
     
         def test_check_empty_list(self):
    @@ -63,3 +65,40 @@ def test_check_revoked(self):
             token_ids = [token_id]
             self.assertRaises(exc.InvalidToken,
                               self._check_with_list, revoked_tokens, token_ids)
    +
    +    def test_check_by_audit_id_revoked(self):
    +        # When the audit ID is in the revocation list, InvalidToken is raised.
    +        audit_id = uuid.uuid4().hex
    +        revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': audit_id}]
    +        revocations = self._setup_revocations(revoked_list)
    +        self.assertRaises(exc.InvalidToken,
    +                          revocations.check_by_audit_id, [audit_id])
    +
    +    def test_check_by_audit_id_chain_revoked(self):
    +        # When the token's audit chain ID is in the revocation list,
    +        # InvalidToken is raised.
    +        revoked_audit_id = uuid.uuid4().hex
    +        revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': revoked_audit_id}]
    +        revocations = self._setup_revocations(revoked_list)
    +
    +        token_audit_ids = [uuid.uuid4().hex, revoked_audit_id]
    +        self.assertRaises(exc.InvalidToken,
    +                          revocations.check_by_audit_id, token_audit_ids)
    +
    +    def test_check_by_audit_id_not_revoked(self):
    +        # When the audit ID is not in the revocation list no exception.
    +        revoked_list = [{'id': uuid.uuid4().hex, 'audit_id': uuid.uuid4().hex}]
    +        revocations = self._setup_revocations(revoked_list)
    +
    +        audit_id = uuid.uuid4().hex
    +        revocations.check_by_audit_id([audit_id])
    +
    +    def test_check_by_audit_id_no_audit_ids(self):
    +        # Older identity servers don't send audit_ids in the revocation list.
    +        # When this happens, check_by_audit_id still works, just doesn't
    +        # verify anything.
    +        revoked_list = [{'id': uuid.uuid4().hex}]
    +        revocations = self._setup_revocations(revoked_list)
    +
    +        audit_id = uuid.uuid4().hex
    +        revocations.check_by_audit_id([audit_id])
    
  • releasenotes/notes/bug-1490804-87c0ff8e764945c1.yaml+15 0 added
    @@ -0,0 +1,15 @@
    +---
    +features:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    The auth_token middleware validates the token's audit IDs during offline
    +    token validation if the Identity server includes audit IDs in the token
    +    revocation list.
    +security:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    [`CVE-2015-7546 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-7546>`_]
    +    A bug is fixed where an attacker could avoid token revocation when the PKI
    +    or PKIZ token provider is used. The complete remediation for this
    +    vulnerability requires the corresponding fix in the Identity (keystone)
    +    project.
    
d5378f173da1

Add audit IDs to revocation events

https://github.com/openstack/keystoneBrant KnudsonDec 1, 2015via ghsa
5 files changed · +61 15
  • keystone/tests/unit/test_backend.py+26 13 modified
    @@ -4124,7 +4124,9 @@ def test_token_crud(self):
             token_id = self._create_token_id()
             data = {'id': token_id, 'a': 'b',
                     'trust_id': None,
    -                'user': {'id': 'testuserid'}}
    +                'user': {'id': 'testuserid'},
    +                'token_data': {'access': {'token': {
    +                    'audit_ids': [uuid.uuid4().hex]}}}}
             data_ref = self.token_provider_api._persistence.create_token(token_id,
                                                                          data)
             expires = data_ref.pop('expires')
    @@ -4159,7 +4161,8 @@ def create_token_sample_data(self, token_id=None, tenant_id=None,
             # FIXME(morganfainberg): These tokens look nothing like "Real" tokens.
             # This should be fixed when token issuance is cleaned up.
             data = {'id': token_id, 'a': 'b',
    -                'user': {'id': user_id}}
    +                'user': {'id': user_id},
    +                'access': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
             if tenant_id is not None:
                 data['tenant'] = {'id': tenant_id, 'name': tenant_id}
             if tenant_id is NULL_OBJECT:
    @@ -4168,7 +4171,7 @@ def create_token_sample_data(self, token_id=None, tenant_id=None,
                 data['expires'] = expires
             if trust_id is not None:
                 data['trust_id'] = trust_id
    -            data.setdefault('access', {}).setdefault('trust', {})
    +            data['access'].setdefault('trust', {})
                 # Testuserid2 is used here since a trustee will be different in
                 # the cases of impersonation and therefore should not match the
                 # token's user_id.
    @@ -4334,17 +4337,21 @@ def test_null_expires_token(self):
     
             self.assertEqual(data_ref, new_data_ref)
     
    -    def check_list_revoked_tokens(self, token_ids):
    -        revoked_ids = [x['id']
    -                       for x in self.token_provider_api.list_revoked_tokens()]
    +    def check_list_revoked_tokens(self, token_infos):
    +        revocation_list = self.token_provider_api.list_revoked_tokens()
    +        revoked_ids = [x['id'] for x in revocation_list]
    +        revoked_audit_ids = [x['audit_id'] for x in revocation_list]
             self._assert_revoked_token_list_matches_token_persistence(revoked_ids)
    -        for token_id in token_ids:
    +        for token_id, audit_id in token_infos:
                 self.assertIn(token_id, revoked_ids)
    +            self.assertIn(audit_id, revoked_audit_ids)
     
         def delete_token(self):
             token_id = uuid.uuid4().hex
    +        audit_id = uuid.uuid4().hex
             data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
    -                'user': {'id': 'testuserid'}}
    +                'user': {'id': 'testuserid'},
    +                'token_data': {'token': {'audit_ids': [audit_id]}}}
             data_ref = self.token_provider_api._persistence.create_token(token_id,
                                                                          data)
             self.token_provider_api._persistence.delete_token(token_id)
    @@ -4356,7 +4363,7 @@ def delete_token(self):
                 exception.TokenNotFound,
                 self.token_provider_api._persistence.delete_token,
                 data_ref['id'])
    -        return token_id
    +        return (token_id, audit_id)
     
         def test_list_revoked_tokens_returns_empty_list(self):
             revoked_ids = [x['id']
    @@ -4407,12 +4414,16 @@ def test_revocation_list_cache(self):
             token_data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
                           'expires': expire_time,
                           'trust_id': None,
    -                      'user': {'id': 'testuserid'}}
    +                      'user': {'id': 'testuserid'},
    +                      'token_data': {'token': {
    +                          'audit_ids': [uuid.uuid4().hex]}}}
             token2_id = uuid.uuid4().hex
             token2_data = {'id_hash': token2_id, 'id': token2_id, 'a': 'b',
                            'expires': expire_time,
                            'trust_id': None,
    -                       'user': {'id': 'testuserid'}}
    +                       'user': {'id': 'testuserid'},
    +                       'token_data': {'token': {
    +                           'audit_ids': [uuid.uuid4().hex]}}}
             # Create 2 Tokens.
             self.token_provider_api._persistence.create_token(token_id,
                                                               token_data)
    @@ -4447,7 +4458,8 @@ def test_revocation_list_cache(self):
         def _test_predictable_revoked_pki_token_id(self, hash_fn):
             token_id = self._create_token_id()
             token_id_hash = hash_fn(token_id.encode('utf-8')).hexdigest()
    -        token = {'user': {'id': uuid.uuid4().hex}}
    +        token = {'user': {'id': uuid.uuid4().hex},
    +                 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
     
             self.token_provider_api._persistence.create_token(token_id, token)
             self.token_provider_api._persistence.delete_token(token_id)
    @@ -4469,7 +4481,8 @@ def test_predictable_revoked_pki_token_id_sha256(self):
     
         def test_predictable_revoked_uuid_token_id(self):
             token_id = uuid.uuid4().hex
    -        token = {'user': {'id': uuid.uuid4().hex}}
    +        token = {'user': {'id': uuid.uuid4().hex},
    +                 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
     
             self.token_provider_api._persistence.create_token(token_id, token)
             self.token_provider_api._persistence.delete_token(token_id)
    
  • keystone/tests/unit/test_backend_sql.py+2 1 modified
    @@ -423,7 +423,8 @@ def test_token_revocation_list_uses_right_columns(self):
             # necessary.
     
             expected_query_args = (token_sql.TokenModel.id,
    -                               token_sql.TokenModel.expires)
    +                               token_sql.TokenModel.expires,
    +                               token_sql.TokenModel.extra,)
     
             with mock.patch.object(token_sql, 'sql') as mock_sql:
                 tok = token_sql.Token()
    
  • keystone/token/persistence/backends/kvs.py+9 0 modified
    @@ -210,6 +210,15 @@ def _add_to_revocation_list(self, data, lock):
                                                           subsecond=True)
             revoked_token_data['id'] = data['id']
     
    +        token_data = data['token_data']
    +        if 'access' in token_data:
    +            # It's a v2 token.
    +            audit_ids = token_data['access']['token']['audit_ids']
    +        else:
    +            # It's a v3 token.
    +            audit_ids = token_data['token']['audit_ids']
    +        revoked_token_data['audit_id'] = audit_ids[0]
    +
             token_list = self._get_key_or_default(self.revocation_key, default=[])
             if not isinstance(token_list, list):
                 # NOTE(morganfainberg): In the case that the revocation list is not
    
  • keystone/token/persistence/backends/sql.py+11 1 modified
    @@ -226,13 +226,23 @@ def list_revoked_tokens(self):
             session = sql.get_session()
             tokens = []
             now = timeutils.utcnow()
    -        query = session.query(TokenModel.id, TokenModel.expires)
    +        query = session.query(TokenModel.id, TokenModel.expires,
    +                              TokenModel.extra)
             query = query.filter(TokenModel.expires > now)
             token_references = query.filter_by(valid=False)
             for token_ref in token_references:
    +            token_data = token_ref[2]['token_data']
    +            if 'access' in token_data:
    +                # It's a v2 token.
    +                audit_ids = token_data['access']['token']['audit_ids']
    +            else:
    +                # It's a v3 token.
    +                audit_ids = token_data['token']['audit_ids']
    +
                 record = {
                     'id': token_ref[0],
                     'expires': token_ref[1],
    +                'audit_id': audit_ids[0],
                 }
                 tokens.append(record)
             return tokens
    
  • releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml+13 0 added
    @@ -0,0 +1,13 @@
    +---
    +features:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    Audit IDs are included in the token revocation list.
    +security:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    [`CVE-2015-7546 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-7546>`_]
    +    A bug is fixed where an attacker could avoid token revocation when the PKI
    +    or PKIZ token provider is used. The complete remediation for this
    +    vulnerability requires the corresponding fix in the keystonemiddleware
    +    project.
    
bff03b5726fe

Add audit IDs to revocation events

https://github.com/openstack/keystoneBrant KnudsonDec 1, 2015via ghsa
5 files changed · +61 15
  • keystone/tests/unit/test_backend.py+26 13 modified
    @@ -4426,7 +4426,9 @@ def test_token_crud(self):
             token_id = self._create_token_id()
             data = {'id': token_id, 'a': 'b',
                     'trust_id': None,
    -                'user': {'id': 'testuserid'}}
    +                'user': {'id': 'testuserid'},
    +                'token_data': {'access': {'token': {
    +                    'audit_ids': [uuid.uuid4().hex]}}}}
             data_ref = self.token_provider_api._persistence.create_token(token_id,
                                                                          data)
             expires = data_ref.pop('expires')
    @@ -4461,7 +4463,8 @@ def create_token_sample_data(self, token_id=None, tenant_id=None,
             # FIXME(morganfainberg): These tokens look nothing like "Real" tokens.
             # This should be fixed when token issuance is cleaned up.
             data = {'id': token_id, 'a': 'b',
    -                'user': {'id': user_id}}
    +                'user': {'id': user_id},
    +                'access': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
             if tenant_id is not None:
                 data['tenant'] = {'id': tenant_id, 'name': tenant_id}
             if tenant_id is NULL_OBJECT:
    @@ -4470,7 +4473,7 @@ def create_token_sample_data(self, token_id=None, tenant_id=None,
                 data['expires'] = expires
             if trust_id is not None:
                 data['trust_id'] = trust_id
    -            data.setdefault('access', {}).setdefault('trust', {})
    +            data['access'].setdefault('trust', {})
                 # Testuserid2 is used here since a trustee will be different in
                 # the cases of impersonation and therefore should not match the
                 # token's user_id.
    @@ -4633,17 +4636,21 @@ def test_null_expires_token(self):
     
             self.assertEqual(data_ref, new_data_ref)
     
    -    def check_list_revoked_tokens(self, token_ids):
    -        revoked_ids = [x['id']
    -                       for x in self.token_provider_api.list_revoked_tokens()]
    +    def check_list_revoked_tokens(self, token_infos):
    +        revocation_list = self.token_provider_api.list_revoked_tokens()
    +        revoked_ids = [x['id'] for x in revocation_list]
    +        revoked_audit_ids = [x['audit_id'] for x in revocation_list]
             self._assert_revoked_token_list_matches_token_persistence(revoked_ids)
    -        for token_id in token_ids:
    +        for token_id, audit_id in token_infos:
                 self.assertIn(token_id, revoked_ids)
    +            self.assertIn(audit_id, revoked_audit_ids)
     
         def delete_token(self):
             token_id = uuid.uuid4().hex
    +        audit_id = uuid.uuid4().hex
             data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
    -                'user': {'id': 'testuserid'}}
    +                'user': {'id': 'testuserid'},
    +                'token_data': {'token': {'audit_ids': [audit_id]}}}
             data_ref = self.token_provider_api._persistence.create_token(token_id,
                                                                          data)
             self.token_provider_api._persistence.delete_token(token_id)
    @@ -4655,7 +4662,7 @@ def delete_token(self):
                 exception.TokenNotFound,
                 self.token_provider_api._persistence.delete_token,
                 data_ref['id'])
    -        return token_id
    +        return (token_id, audit_id)
     
         def test_list_revoked_tokens_returns_empty_list(self):
             revoked_ids = [x['id']
    @@ -4706,12 +4713,16 @@ def test_revocation_list_cache(self):
             token_data = {'id_hash': token_id, 'id': token_id, 'a': 'b',
                           'expires': expire_time,
                           'trust_id': None,
    -                      'user': {'id': 'testuserid'}}
    +                      'user': {'id': 'testuserid'},
    +                      'token_data': {'token': {
    +                          'audit_ids': [uuid.uuid4().hex]}}}
             token2_id = uuid.uuid4().hex
             token2_data = {'id_hash': token2_id, 'id': token2_id, 'a': 'b',
                            'expires': expire_time,
                            'trust_id': None,
    -                       'user': {'id': 'testuserid'}}
    +                       'user': {'id': 'testuserid'},
    +                       'token_data': {'token': {
    +                           'audit_ids': [uuid.uuid4().hex]}}}
             # Create 2 Tokens.
             self.token_provider_api._persistence.create_token(token_id,
                                                               token_data)
    @@ -4746,7 +4757,8 @@ def test_revocation_list_cache(self):
         def _test_predictable_revoked_pki_token_id(self, hash_fn):
             token_id = self._create_token_id()
             token_id_hash = hash_fn(token_id).hexdigest()
    -        token = {'user': {'id': uuid.uuid4().hex}}
    +        token = {'user': {'id': uuid.uuid4().hex},
    +                 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
     
             self.token_provider_api._persistence.create_token(token_id, token)
             self.token_provider_api._persistence.delete_token(token_id)
    @@ -4768,7 +4780,8 @@ def test_predictable_revoked_pki_token_id_sha256(self):
     
         def test_predictable_revoked_uuid_token_id(self):
             token_id = uuid.uuid4().hex
    -        token = {'user': {'id': uuid.uuid4().hex}}
    +        token = {'user': {'id': uuid.uuid4().hex},
    +                 'token_data': {'token': {'audit_ids': [uuid.uuid4().hex]}}}
     
             self.token_provider_api._persistence.create_token(token_id, token)
             self.token_provider_api._persistence.delete_token(token_id)
    
  • keystone/tests/unit/test_backend_sql.py+2 1 modified
    @@ -492,7 +492,8 @@ def test_token_revocation_list_uses_right_columns(self):
             # necessary.
     
             expected_query_args = (token_sql.TokenModel.id,
    -                               token_sql.TokenModel.expires)
    +                               token_sql.TokenModel.expires,
    +                               token_sql.TokenModel.extra,)
     
             with mock.patch.object(token_sql, 'sql') as mock_sql:
                 tok = token_sql.Token()
    
  • keystone/token/persistence/backends/kvs.py+9 0 modified
    @@ -210,6 +210,15 @@ def _add_to_revocation_list(self, data, lock):
                                                           subsecond=True)
             revoked_token_data['id'] = data['id']
     
    +        token_data = data['token_data']
    +        if 'access' in token_data:
    +            # It's a v2 token.
    +            audit_ids = token_data['access']['token']['audit_ids']
    +        else:
    +            # It's a v3 token.
    +            audit_ids = token_data['token']['audit_ids']
    +        revoked_token_data['audit_id'] = audit_ids[0]
    +
             token_list = self._get_key_or_default(self.revocation_key, default=[])
             if not isinstance(token_list, list):
                 # NOTE(morganfainberg): In the case that the revocation list is not
    
  • keystone/token/persistence/backends/sql.py+11 1 modified
    @@ -228,13 +228,23 @@ def list_revoked_tokens(self):
             session = sql.get_session()
             tokens = []
             now = timeutils.utcnow()
    -        query = session.query(TokenModel.id, TokenModel.expires)
    +        query = session.query(TokenModel.id, TokenModel.expires,
    +                              TokenModel.extra)
             query = query.filter(TokenModel.expires > now)
             token_references = query.filter_by(valid=False)
             for token_ref in token_references:
    +            token_data = token_ref[2]['token_data']
    +            if 'access' in token_data:
    +                # It's a v2 token.
    +                audit_ids = token_data['access']['token']['audit_ids']
    +            else:
    +                # It's a v3 token.
    +                audit_ids = token_data['token']['audit_ids']
    +
                 record = {
                     'id': token_ref[0],
                     'expires': token_ref[1],
    +                'audit_id': audit_ids[0],
                 }
                 tokens.append(record)
             return tokens
    
  • releasenotes/notes/bug-1490804-de58a9606edb31eb.yaml+13 0 added
    @@ -0,0 +1,13 @@
    +---
    +features:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    Audit IDs are included in the token revocation list.
    +security:
    +  - >
    +    [`bug 1490804 <https://bugs.launchpad.net/keystone/+bug/1490804>`_]
    +    [`CVE-2015-7546 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-7546>`_]
    +    A bug is fixed where an attacker could avoid token revocation when the PKI
    +    or PKIZ token provider is used. The complete remediation for this
    +    vulnerability requires the corresponding fix in the keystonemiddleware
    +    project.
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

12

News mentions

0

No linked articles in our index yet.