我正在尝试将
%Y%m%d%H%M%S%Z
格式的证书到期日期转换为纪元,该日期将用于与从 Java 密钥库收集的另一个日期进行比较。为了保持简单(因为证书日期是 UTC/Zulu,Java 密钥库采用 CST),我想我会将日期转换为 UTC 和纪元,以便稍后在我的剧本中进行比较。但是,我收到一条错误,指出我的变量无法转换为字典。
以下是我收到错误之前的证书任务。
- name: Verifying Server Cert is present
ansible.builtin.stat:
path: /opt/ssl/{{ ansible_facts['hostname'] }}.crt
register: cert_file
tags: debug
- name: End play if cert if not found.
ansible.builtin.assert:
that:
- cert_file.stat.exists == true
fail_msg: Server Cert not found.
tags: debug
- name: Find cert files under /opt/ssl
ansible.builtin.find:
paths: /opt/ssl
file_type: file
patterns: "*.crt"
recurse: true
register: find_result
tags: cert
when: cert_file.stat.exists == true
- name: Gather Cert info
openssl_certificate_info:
path: "{{ item.path }}"
register: cert_info
loop: "{{ find_result.files }}"
tags: cert
when: cert_file.stat.exists == true
- name: debug cert_info
debug:
msg: "{{ cert_info }}"
- name: Set full certificate expiration fact
ansible.builtin.set_fact:
cert_exp_full: "{{ item.not_after }}"
loop: "{{ cert_info.results }}"
loop_control:
label: "{{ item.subject.commonName}}"
tags: cert
when: cert_file.stat.exists == true
- name: debug
debug:
msg: "{{ cert_exp_full }}"
- name: Convert to epoch | Times are in UTC/Zulu
ansible.builtin.set_fact:
cert_epoch: "{{ (cert_exp_full | to_datetime('%Y%m%d%H%M%S%z')).strftime('%s') }}"
tags: cert
when: cert_file.stat.exists == true
那么输出如下:
PLAY [all] *****************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************************
ok: [dtest08]
TASK [certs : Verifying Server Cert is present] ****************************************************************************************************************************************************************************
ok: [dtest08]
TASK [certs : End play if cert if not found.] ******************************************************************************************************************************************************************************
ok: [dtest08] => changed=false
msg: All assertions passed
TASK [certs : Find cert files under /opt/ssl] ******************************************************************************************************************************************************************************
ok: [dtest08]
TASK [certs : Gather Cert info] ********************************************************************************************************************************************************************************************
ok: [dtest08] => (item={'path': '/opt/ssl/dtest08.crt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 1253, 'inode': 34241578, 'dev': 64768, 'nlink': 1, 'atime': 1704382642.2240086, 'mtime': 1675972923.0, 'ctime': 1701979001.5420384, 'gr_name': 'root', 'pw_name': 'root', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
TASK [certs : debug cert_info] *********************************************************************************************************************************************************************************************
ok: [dtest08] =>
msg:
changed: false
msg: All items completed
results:
- ansible_loop_var: item
authority_cert_issuer: null
authority_cert_serial_number: null
authority_key_identifier: null
basic_constraints: null
basic_constraints_critical: false
changed: false
expired: false
extended_key_usage: null
extended_key_usage_critical: false
extensions_by_oid: {}
failed: false
invocation:
module_args:
path: /opt/ssl/dtest08.crt
select_crypto_backend: auto
valid_at: null
issuer:
commonName: dtest
countryName: US
emailAddress: [email protected]
localityName: Sheboygan
organizationName: Default Company Ltd
stateOrProvinceName: Wisconsin
issuer_ordered:
- - countryName
- US
- - stateOrProvinceName
- Wisconsin
- - localityName
- Sheboygan
- - organizationName
- Default Company Ltd
- - commonName
- dtest
- - emailAddress
- [email protected]
item:
atime: 1704382642.2240086
ctime: 1701979001.5420384
dev: 64768
gid: 0
gr_name: root
inode: 34241578
isblk: false
ischr: false
isdir: false
isfifo: false
isgid: false
islnk: false
isreg: true
issock: false
isuid: false
mode: '0644'
mtime: 1675972923.0
nlink: 1
path: /opt/ssl/dtest08.crt
pw_name: root
rgrp: true
roth: true
rusr: true
size: 1253
uid: 0
wgrp: false
woth: false
wusr: true
xgrp: false
xoth: false
xusr: false
key_usage: null
key_usage_critical: false
not_after: 20240209200203Z
not_before: 20230209200203Z
ocsp_must_staple: null
ocsp_must_staple_critical: false
ocsp_uri: null
public_key: |-
-----BEGIN PUBLIC KEY-----
<REMOVED>
-----END PUBLIC KEY-----
public_key_fingerprints:
blake2b: <REMOVED>
blake2s: <REMOVED>
md5: <REMOVED>
sha1: <REMOVED>
sha224: <REMOVED>
sha256: <REMOVED>
sha384: <REMOVED>
sha3_224: <REMOVED>
sha3_256: <REMOVED>
sha3_384: <REMOVED>
sha3_512: <REMOVED>
sha512: <REMOVED>
shake_128: <REMOVED>
shake_256: <REMOVED>
serial_number: <REMOVED>
signature_algorithm: sha256WithRSAEncryption
subject:
commonName: dtest08
countryName: US
localityName: Sheboyga
organizationName: Default Company Ltd
stateOrProvinceName: Wisconsin
subject_alt_name: null
subject_alt_name_critical: false
subject_key_identifier: null
subject_ordered:
- - countryName
- US
- - stateOrProvinceName
- Wisconsin
- - localityName
- Sheboyga
- - organizationName
- Default Company Ltd
- - commonName
- dtest08
valid_at: {}
version: 1
TASK [certs : Set full certificate expiration fact] ************************************************************************************************************************************************
ok: [dtest08] => (item=dtest08)
TASK [certs : debug] *******************************************************************************************************************************************************************************************************
ok: [dtest08] =>
msg: 20240209200203Z
TASK [certs : Convert to epoch | Times are in UTC/Zulu] ********************************************************************************************************************************************************************
fatal: [dtest08]: FAILED! =>
msg: |-
the field 'args' has an invalid value ({'cert_epoch': "{{ (cert_exp_full | to_datetime('%Y%m%d%H%M%S%z')).strftime('%s') }}"}), and could not be converted to an dict.The error was: time data '20240209200203Z' does not match format '%Y%m%d%H%M%S%z'
The error appears to be in '/root/ansible/certs/roles/certs/tasks/main.yml': line 49, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Convert to epoch | Times are in UTC/Zulu
^ here
可能导致我的问题的另一个项目是我需要使用的 python 和 ansible 版本。
# ansible --version
ansible 2.9.25
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Jun 14 2022, 12:54:58) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)]
在运行 ansible v2.15.4 和 python3.11 的本地服务器上,这是有效的。
如何使用 ansible 2.9.25 和 python 3.6 克服此错误?我假设这是一个我不知道的语法问题(我对 python 不太熟悉)。提前致谢。
%z 是导致问题的原因 正确的时间格式为 %Y%m%d%H%M%SZ
Python 中的类似问题已被问到这里 如何将祖鲁时间换算为新纪元?
我尝试过的示例剧本
- name: Convert certificate expiration date to epoch
hosts: localhost
gather_facts: false
tasks:
- name: Set certificate expiration date
set_fact:
cert_exp_date: '20240209200203Z'
- name: Convert date to epoch
ansible.builtin.set_fact:
cert_epoch: "{{ (cert_exp_date | to_datetime('%Y%m%d%H%M%SZ')).strftime('%s') }}"
输出:
TASK [Convert date to epoch] ****************************************************************************************
ok: [localhost] => {"ansible_facts": {"cert_epoch": "1707508923"}, "changed": false}
用Python测试
Python 3.8.10 (default, Nov 22 2023, 10:22:35)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> date_str = '20240209200203Z'
>>> date_obj = datetime.strptime(date_str, "%Y%m%d%H%M%SZ")
>>> int(date_obj.timestamp())
1707508923