Ansible uri模块和2路TLS

时间:2018-12-17 08:10:09

标签: ssl ansible ssl-certificate

让uri模块与2路TLS一起正常播放似乎存在问题。我设法使客户端验证或服务器验证有效,但不能同时进行,这似乎很奇怪。如下所示,相同的设置可以正常使用cURL。如果您对uri模块和TLS有一定的经验,也许可以为您提供帮助。

设置

我已将Apache httpd设置为在本地主机上接受TLS连接,并带有自签名根证书,中间CA证书,针对127.0.0.1发行的服务器证书和客户端证书。我可以使用cURL测试此设置,一切正常,请参见下文。

文件host.127.0.0.1.cert.pem包含三个证书:根证书,中间证书和服务器证书。 文件ca.chain.pem包含两个证书:根证书和中间证书。 文件client.SomeUser.cert.pem包含一个证书:客户端证书

从下面的输出中可以看到,我正在运行python version = 3.7.0

来自httpd.conf:

Listen 443
<VirtualHost *:443>
    ServerName 127.0.0.1
    SSLEngine on
    SSLCertificateFile "/path/to/host.127.0.0.1.cert.pem"
    SSLCertificateKeyFile "/path/to/host.127.0.0.1.privkey.nopass.pem"
    SSLVerifyClient require
    SSLVerifyDepth 2
    SSLCACertificateFile "/path/to/ca.chain.pem"
</VirtualHost>

使用CURL测试设置

cURL命令和输出:

$ curl -vvv  --cert client.SomeUser.cert.pem --key client.SomeUser.privkey.pem --cacert ca.chain.pem -X GET https://127.0.0.1
* Connected to 127.0.0.1 (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
Enter PEM pass phrase:
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /Users/mans/devel/phenixid/test-ca/src/test/resources/fixtures/tls/ca1/ca.chain.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=SE; ST=Nacka; L=Nacka Strand; O=Example; OU=Testers; CN=127.0.0.1
*  start date: Dec 14 11:45:08 2018 GMT
*  expire date: Dec 21 11:45:08 2018 GMT
*  subjectAltName: host "127.0.0.1" matched cert's IP address!
*  issuer: C=SE; ST=Nacka; O=Example; OU=Testers; CN=Example Intermediate CA 1
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 14 Dec 2018 15:03:31 GMT
< Server: Apache/2.4.33 (Unix) LibreSSL/2.2.7
< Content-Location: index.html.en
< Vary: negotiate
< TCN: choice
< Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
< ETag: "2d-432a5e4a73a80"
< Accept-Ranges: bytes
< Content-Length: 45
< Content-Type: text/html
<
<html><body><h1>It works!</h1></body></html>

使用ANSI测试设置

我的烦人的任务看起来像这样:

- name: "GET"
  uri:
    method: GET
    url: https://127.0.0.1/
    validate_certs: yes
    client_cert: "client.SomeUser.cert.pem"
    client_key: "client.SomeUser.privkey.pem"

这是我尝试运行剧本的尝试:

  • 如果我在服务器端关闭了证书验证,并且如果我在SSL_CERT_FILE env var中包含CA链,则客户端将接受服务器证书。好。
  • 如果我在服务器端打开了证书验证,但在客户端将其关闭(validate_certs:否),则服务器接受客户端证书。好。
  • 但是,如果我同时打开双方的证书验证,则客户端将无法接受服务器证书。不好

这是ansible命令,失败时将输出:

$ SSL_CERT_FILE=/path/to/ca.chain.pem ansible-playbook my-playbook.yml -vvv
ansible-playbook 2.7.4
  config file = /Users/xxx/.ansible.cfg
  configured module search path = ['/Users/xxx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/xxx/virtualenvs/p3/lib/python3.7/site-packages/ansible
  executable location = /Users/xxx/virtualenvs/p3/bin/ansible-playbook
  python version = 3.7.0 (default, Aug 22 2018, 15:22:33) [Clang 9.1.0 (clang-902.0.39.2)]
Using /Users/xxx/.ansible.cfg as config file
/etc/ansible/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/etc/ansible/hosts did not meet script requirements, check plugin documentation if this is unexpected
Parsed /etc/ansible/hosts inventory source with ini plugin
......output omitted......
The full traceback is:
  File "/var/folders/78/n3ytyhrs2415sl3h8h1fms000000gn/T/ansible_uri_payload_bus4199a/ansible_uri_payload.zip/ansible/module_utils/urls.py", line 1259, in fetch_url
    client_key=client_key, cookies=cookies)
  File "/var/folders/78/n3ytyhrs2415sl3h8h1fms000000gn/T/ansible_uri_payload_bus4199a/ansible_uri_payload.zip/ansible/module_utils/urls.py", line 1162, in open_url
    client_cert=client_cert, client_key=client_key, cookies=cookies)
  File "/var/folders/78/n3ytyhrs2415sl3h8h1fms000000gn/T/ansible_uri_payload_bus4199a/ansible_uri_payload.zip/ansible/module_utils/urls.py", line 1070, in open
    r = urllib_request.urlopen(*urlopen_args)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 523, in open
    req = meth(req)
  File "/var/folders/78/n3ytyhrs2415sl3h8h1fms000000gn/T/ansible_uri_payload_bus4199a/ansible_uri_payload.zip/ansible/module_utils/urls.py", line 779, in http_request
    build_ssl_validation_error(self.hostname, self.port, paths_checked, e)
  File "/var/folders/78/n3ytyhrs2415sl3h8h1fms000000gn/T/ansible_uri_payload_bus4199a/ansible_uri_payload.zip/ansible/module_utils/urls.py", line 580, in build_ssl_validation_error
    raise SSLValidationError(' '.join(msg) % (hostname, port, ", ".join(paths)))

fatal: [127.0.0.1]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "attributes": null,
            "backup": null,
            "body": null,
            "body_format": "raw",
            "client_cert": "/path/to/client.SomeUser.cert.pem",
            "client_key": "/path/to/client.SomeUser.privkey.pem",
            "content": null,
            "creates": null,
            "delimiter": null,
            "dest": null,
            "directory_mode": null,
            "follow": false,
            "follow_redirects": "safe",
            "force": false,
            "force_basic_auth": false,
            "group": null,
            "headers": {},
            "http_agent": "ansible-httpget",
            "method": "GET",
            "mode": null,
            "owner": null,
            "regexp": null,
            "remote_src": null,
            "removes": null,
            "return_content": false,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "status_code": [
                200
            ],
            "timeout": 30,
            "unsafe_writes": null,
            "url": "https://127.0.0.1/",
            "url_password": null,
            "url_username": null,
            "use_proxy": true,
            "validate_certs": true
        }
    },
    "msg": "Failed to validate the SSL certificate for 127.0.0.1:443. Make sure your managed systems have a valid CA certificate installed. You can use validate_certs=False if you do not need to confirm the servers identity but this is unsafe and not recommended. Paths checked for this platform: /etc/ssl/certs, /etc/ansible, /usr/local/etc/openssl. The exception msg was: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1045)."
}

如上所述,ansible-playbook调用非常适合客户端证书的服务器验证或服务器证书的客户端验证,但不能同时使用。由于使用cURL可以正常工作,因此我猜测uri模块处理TLS的方式一定有问题。任何帮助表示赞赏。

0 个答案:

没有答案