我正在构建一组Anable任务,使用它们的API通过Namecheap续订HTTPS证书.他们的API返回XML响应,所以我一直在使用Ansible Community ity.General al.xml模块来解析我从每个响应中需要的内容.其中一项任务是连接每个中间证书以构建证书链文件,但Ansible模块返回的属性名包括特殊字符以指示XML名称空间.

以下是来自Namecheap API端点的示例响应.我正在try 获取三个<Certificate> node ,每个 node 都在其自己的<Certificate Type="INTERMEDIATE"> node 内.

<?xml version="1.0" encoding="UTF-8"?>
<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
    <Errors/>
    <Warnings/>
    <RequestedCommand>namecheap.ssl.getInfo</RequestedCommand>
    <CommandResponse Type="namecheap.ssl.getInfo">
        <SSLGetInfoResult Status="active" StatusDescription="Certificate is Active." Type="EssentialSSL Wildcard" IssuedOn="9/8/2022" Years="1" Expires="9/22/2023" ActivationExpireDate="" OrderId="1234567890" SANSCount="0">
            <CertificateDetails>
                <CSR>
                    <![CDATA[-----BEGIN CERTIFICATE REQUEST----- ... -----END CERTIFICATE REQUEST-----]]>
                </CSR>
                <ApproverEmail>CNAMECSRHASH</ApproverEmail>
                <CommonName>*.example.com</CommonName>
                <AdministratorEmail>example@example.com</AdministratorEmail>
                <Certificates CertificateReturned="true" ReturnType="INDIVIDUAL">
                    <Certificate>
                        <![CDATA[-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----]]>
                    </Certificate>
                    <CaCertificates>
                        <Certificate Type="INTERMEDIATE">
                            <Certificate>
                                <![CDATA[-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----]]>
                            </Certificate>
                        </Certificate>
                        <Certificate Type="INTERMEDIATE">
                            <Certificate>
                                <![CDATA[-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----]]>
                            </Certificate>
                        </Certificate>
                        <Certificate Type="INTERMEDIATE">
                            <Certificate>
                                <![CDATA[-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----]]>
                            </Certificate>
                        </Certificate>
                    </CaCertificates>
                </Certificates>
            </CertificateDetails>
            <Provider>
                <OrderID>1234567890</OrderID>
                <Name>COMODO</Name>
            </Provider>
        </SSLGetInfoResult>
    </CommandResponse>
    <Server>e4fee023b712</Server>
    <GMTTimeDifference>--5:00</GMTTimeDifference>
    <ExecutionTime>0.117</ExecutionTime>
</ApiResponse>

这是我目前正在处理的一组可分析任务的"基线".

- name: parse info response for cert chain
  community.general.xml:
    xmlstring: "{{ namecheap_info.content }}"
    namespaces:
      x: 'http://api.namecheap.com/xml.response'
    xpath: '/x:ApiResponse/x:CommandResponse/x:SSLGetInfoResult/x:CertificateDetails/x:Certificates/x:CaCertificates/x:Certificate/x:Certificate'
    content: text
  register: parsed_cert_chain

- ansible.builtin.set_fact:
    namecheap_cert_chain_content: "{{ parsed_cert_chain.matches | map(attribute='{http://api.namecheap.com/xml.response}Certificate') }}"

当我运行这些任务时,我从ansible.Builtin.set_act模块得到一个错误:The task includes an option with an undefined variable. The error was: 'dict object' has no attribute '{http://api'..我知道这是因为URL中的句点被视为属性访问器,但我还没有成功地弄清楚如何转义它.

以下是我try 过的一些方法(请注意,其中一些只是在黑暗中拍摄)及其各自的错误消息:

  • 在句点('dict object' has no attribute '{http://api\\\\'.)上使用反斜杠
  • 句点上的双反斜杠('dict object' has no attribute '{http://api\\\\\\\\'.)
  • 大括号上的反斜杠('dict object' has no attribute '\\\\{http://api'.)
  • 使用方括号将字符串括起来(请参见https://stackoverflow.com/a/55223203)(dict object has no element ['{http://api.namecheap.com/xml.response}Certificate'].)
  • try 字符串内侧的方括号('dict object' has no attribute '[{http://api'.)

我想我可以在将字符串传递到XML模块之前使用替换过滤器从字符串中删除XML名称空间,但这感觉有点像创可贴.转义map(attribute)JJAA2过滤器的特殊字符的正确方法是什么?

推荐答案

如果使用json_query而不是map,则可以执行以下操作:

- name: parse info response for cert chain
  community.general.xml:
    xmlstring: "{{ namecheap_info.content }}"
    namespaces:
      x: 'http://api.namecheap.com/xml.response'
    xpath: '/x:ApiResponse/x:CommandResponse/x:SSLGetInfoResult/x:CertificateDetails/x:Certificates/x:CaCertificates/x:Certificate/x:Certificate'
    content: text
  register: parsed_cert_chain

- ansible.builtin.set_fact:
    namecheap_cert_chain_content: >-
      {{
        parsed_cert_chain.matches | json_query('[*]."{http://api.namecheap.com/xml.response}Certificate"')
      }}

- debug:
    var: namecheap_cert_chain_content

这将产生:

TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "namecheap_cert_chain_content": [
        "\n                                -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\n                            ",
        "\n                                -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\n                            ",
        "\n                                -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\n                            "
    ]
}

Python相关问答推荐

列表上值总和最多为K(以O(log n))的最大元素数

Python会扔掉未使用的表情吗?

Pandas实际上如何对基于自定义的索引(integer和非integer)执行索引

numba jitClass,记录类型为字符串

重新匹配{ }中包含的文本,其中文本可能包含{{var}

如何避免Chained when/then分配中的Mypy不兼容类型警告?

从一个系列创建一个Dataframe,特别是如何重命名其中的列(例如:使用NAs/NaN)

实现自定义QWidgets作为QTimeEdit的弹出窗口

如何在UserSerializer中添加显式字段?

pandas:对多级列框架的列进行排序/重新排序

下三角形掩码与seaborn clustermap bug

基于另一列的GROUP-BY聚合将列添加到Polars LazyFrame

Python—在嵌套列表中添加相同索引的元素,然后计算平均值

如何将泛型类类型与函数返回类型结合使用?

504未连接IB API TWS错误—即使API连接显示已接受''

每次查询的流通股数量

高效生成累积式三角矩阵

在matplotlib中重叠极 map 以创建径向龙卷风图

仅取消堆叠最后三列

Match-Case构造中的对象可调用性测试