Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use session instead of login #34

Open
glimchb opened this issue Feb 23, 2024 · 5 comments
Open

use session instead of login #34

glimchb opened this issue Feb 23, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@glimchb
Copy link
Member

glimchb commented Feb 23, 2024

see https://docs.ansible.com/ansible/latest/collections/community/general/redfish_command_module.html#examples

trying something like this:

- name: Create session
  community.general.redfish_command:
    category: Sessions
    command: CreateSession
    baseuri: "{{ inventory_hostname }}"
    username: "{{ dpu_bmc_username }}"
    password: "{{ dpu_bmc_password }}"
  delegate_to: localhost
  register: result_session

- name: Extract session details from login result
  ansible.builtin.set_fact:
    bmc_firmware_update_token: "{{ result_session.session.token }}"
    bmc_firmware_update_uri: "{{ result_session.session.uri }}"

- name: Print Session Tokens
  ansible.builtin.debug:
    msg:
      - "{{ bmc_firmware_update_token }}"
      - "{{ bmc_firmware_update_uri }}"

- name: Get Firmware Inventory
  community.general.redfish_info:
    category: Update
    command: GetFirmwareInventory
    baseuri: "{{ inventory_hostname }}"
    auth_token: "{{ bmc_firmware_update_token }}"
    # username: "{{ dpu_bmc_username }}"
    # password: "{{ dpu_bmc_password }}"
  register: result
  delegate_to: localhost

- name: Delete session using security token created by CreateSesssion above
  community.general.redfish_command:
    category: Sessions
    command: DeleteSession
    baseuri: "{{ inventory_hostname }}"
    auth_token: "{{ bmc_firmware_update_token }}"
    session_uri: "{{ bmc_firmware_update_uri }}"
  delegate_to: localhost

I get

2024-03-01 18:58:29     "msg": "Action was successful",
2024-03-01 18:58:29     "return_values": {},
2024-03-01 18:58:29     "session": {
2024-03-01 18:58:29         "token": "2M5740CIEQhDqLelfLSU",
2024-03-01 18:58:29         "uri": "/redfish/v1/SessionService/Sessions/EeMxklMJZo"
2024-03-01 18:58:29     }
2024-03-01 18:58:29 }

but fails on

2024-03-01 18:58:32 fatal: [10.246.87.133 -> localhost]: FAILED! => {
2024-03-01 18:58:32     "changed": false,
2024-03-01 18:58:32     "invocation": {
2024-03-01 18:58:32         "module_args": {
2024-03-01 18:58:32             "auth_token": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
2024-03-01 18:58:32             "baseuri": "10.246.87.133",
2024-03-01 18:58:32             "category": [
2024-03-01 18:58:32                 "Update"
2024-03-01 18:58:32             ],
2024-03-01 18:58:32             "command": [
2024-03-01 18:58:32                 "GetFirmwareInventory"
2024-03-01 18:58:32             ],
2024-03-01 18:58:32             "manager": null,
2024-03-01 18:58:32             "password": null,
2024-03-01 18:58:32             "timeout": null,
2024-03-01 18:58:32             "update_handle": null,
2024-03-01 18:58:32             "username": null
2024-03-01 18:58:32         }
2024-03-01 18:58:32     },
2024-03-01 18:58:32     "msg": "HTTP Error 401 on GET request to 'https://10.246.87.133/redfish/v1/UpdateService', extended message: 'While accessing the resource at '/redfish/v1/UpdateService', the service received an authorization error 'Invalid username or password'.'"
2024-03-01 18:58:32 }

curl seems working...

curl -k -H "X-Auth-Token: eFzrs6HNLSYtA0y0IczW" -X GET https://10.246.87.133/redfish/v1/UpdatService/FirmwareInventory
@jcastanos2
Copy link
Contributor

``Traceback (most recent call last):
  File "/usr/lib/python3.10/urllib/request.py", line 1348, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.10/http/client.py", line 1283, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1329, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1278, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.10/http/client.py", line 1038, in _send_output
    self.send(msg)
  File "/usr/lib/python3.10/http/client.py", line 976, in send
    self.connect()
  File "/usr/lib/python3.10/http/client.py", line 1455, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/usr/lib/python3.10/ssl.py", line 513, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.10/ssl.py", line 1100, in _create
    self.do_handshake()
  File "/usr/lib/python3.10/ssl.py", line 1371, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed \
certificate (_ssl.c:1007)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/sancho/opi/ansible-opi-dpu/./jgctests/get.py", line 177, in <module>
    main()
  File "/home/sancho/opi/ansible-opi-dpu/./jgctests/get.py", line 174, in main
    utils.open_url("GET", "https://10.137.189.246/redfish/v1/UpdateService")
  File "/home/sancho/opi/ansible-opi-dpu/./jgctests/get.py", line 167, in open_url
    r = urllib_request.urlopen(request, None, timeout)
  File "/usr/lib/python3.10/urllib/request.py", line 216, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.10/urllib/request.py", line 519, in open
    response = self._open(req, data)
  File "/usr/lib/python3.10/urllib/request.py", line 536, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.10/urllib/request.py", line 496, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.10/urllib/request.py", line 1391, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.10/urllib/request.py", line 1351, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self\
-signed certificate (_ssl.c:1007)>

It can be fixed by making the following change in

/usr/lib/python3/dist-packages/ansible/module_utils/urls.py
def open(self, method, url, data=None, headers=None, use_proxy=None,
             force=None, last_mod_time=None, timeout=None, validate_certs=None,
             url_username=None, url_password=None, http_agent=None,
             force_basic_auth=None, follow_redirects=None,
             client_cert=None, client_key=None, cookies=None, use_gssapi=False,
             unix_socket=None, ca_path=None, unredirected_headers=None, decompress=None,
             ciphers=None, use_netrc=None):
...

        context = ssl._create_unverified_context()
        r = urllib_request.urlopen(request, None, timeout, context=context)

But likely this is not the right fix

@glimchb
Copy link
Member Author

glimchb commented Mar 5, 2024

I think I have reproduction with basic python (3.6.8) and also enabled debug prints now:

this works (from https://github.com/DMTF/python-redfish-library/blob/main/src/redfish/rest/v1.py) :

import http.client
http.client.HTTPConnection.debuglevel = 1

import redfish
r = redfish.redfish_client(base_url='https://10.246.87.133')
for x in range(3):
	s = r.get('/redfish/v1/UpdateService', headers={'X-Auth-Token' : "iwKUR3no1WOHB5PFkd5H"})
	print(s.status)
	print(s.text)

and this works:

import http.client
http.client.HTTPConnection.debuglevel = 1

import requests
s = requests.Session()
for x in range(3):
	resp = s.request("GET", "https://10.246.87.133/redfish/v1/UpdateService", headers={'X-Auth-Token' : "iwKUR3no1WOHB5PFkd5H"}, verify=False)
	print(resp)

vs fails:

import ssl
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

import urllib.request
handler = urllib.request.HTTPSHandler(debuglevel=1, context=ctx)
opener = urllib.request.build_opener(handler)
opener.addheaders = [('X-Auth-Token', 'iwKUR3no1WOHB5PFkd5H')]
for x in range(3):
	response = opener.open("https://10.246.87.133/redfish/v1/UpdateService")
	print(response.read())

When it fails, first iteration is ok, second is failed (that's why range in the code)
Also important, session object is deleted on the BMC side...
Will debug more tomorrow...

working debug info:

send: b'GET /redfish/v1/UpdateService HTTP/1.1\r\nHost: 10.246.87.133\r\nUser-Agent: python-requests/2.27.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nX-Auth-Token: iwKUR3no1WOHB5PFkd5H\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: OData-Version: 4.0
header: Allow: GET, PATCH, HEAD
header: ETag: "2BB654F0"
header: Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
header: X-Frame-Options: DENY
header: Pragma: no-cache
header: Cache-Control: no-Store,no-Cache
header: X-XSS-Protection: 1; mode=block
header: X-Content-Type-Options: nosniff
header: Content-Security-Policy: default-src 'none'; img-src 'self' data:; font-src 'self'; style-src 'self'; script-src 'self'; connect-src 'self' wss:; form-action 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'none'
header: Content-Type: application/json
header: Date: Tue, 05 Mar 2024 03:54:39 GMT
header: Content-Length: 1821
<Response [200]>

failed debug info:

send: b'GET /redfish/v1/UpdateService HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: 10.246.87.133\r\nX-Auth-Token: iwKUR3no1WOHB5PFkd5H\r\nAccept: */*\r\nConnection: close\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: OData-Version: 4.0
header: Allow: GET, PATCH, HEAD
header: ETag: "2BB654F0"
header: Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
header: X-Frame-Options: DENY
header: Pragma: no-cache
header: Cache-Control: no-Store,no-Cache
header: X-XSS-Protection: 1; mode=block
header: X-Content-Type-Options: nosniff
header: Content-Security-Policy: default-src 'none'; img-src 'self' data:; font-src 'self'; style-src 'self'; script-src 'self'; connect-src 'self' wss:; form-action 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'none'
header: Content-Type: application/json
header: Date: Tue, 05 Mar 2024 03:56:50 GMT
header: Connection: close
header: Content-Length: 1821
b'{\n  "@odata.id": "/redfish/v1/UpdateService",\n  "@odata.type": "#UpdateService.v1_8_0.UpdateService",\n  "Actions": {\n    "#UpdateService.SimpleUpdate": {\n      "[email protected]": [\n        [\n          "SCP"\n        ]\n      ],\n      "target": "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate"\n    },\n    "Oem": {\n      "Nvidia": {\n        "#NvidiaUpdateService.CommitImage": {\n          "@Redfish.ActionInfo": "/redfish/v1/UpdateService/Oem/Nvidia/CommitImageActionInfo",\n          "target": "/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.CommitImage"\n        },\n        "#NvidiaUpdateService.PublicKeyExchange": {\n          "target": "/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.PublicKeyExchange"\n        },\n        "#NvidiaUpdateService.RevokeAllRemoteServerPublicKeys": {\n          "target": "/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.RevokeAllRemoteServerPublicKeys"\n        }\n      }\n    }\n  },\n  "Description": "Service for Software Update",\n  "FirmwareInventory": {\n    "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory"\n  },\n  "HttpPushUri": "/redfish/v1/UpdateService/update",\n  "HttpPushUriOptions": {\n    "HttpPushUriApplyTime": {\n      "ApplyTime": "OnReset"\n    }\n  },\n  "HttpPushUriTargets": [],\n  "Id": "UpdateService",\n  "MaxImageSizeBytes": 209715200,\n  "MultipartHttpPushUri": "/redfish/v1/UpdateService/update-multipart",\n  "[email protected]": {\n    "@odata.type": "#Settings.v1_3_3.OperationApplyTimeSupport",\n    "SupportedValues": [\n      "Immediate"\n    ]\n  },\n  "Name": "Update Service",\n  "ServiceEnabled": true,\n  "SoftwareInventory": {\n    "@odata.id": "/redfish/v1/UpdateService/SoftwareInventory"\n  },\n  "Status": {\n    "Conditions": [],\n    "State": "Enabled"\n  }\n}'
send: b'GET /redfish/v1/UpdateService HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: 10.246.87.133\r\nX-Auth-Token: iwKUR3no1WOHB5PFkd5H\r\nAccept: */*\r\nConnection: close\r\n\r\n'
reply: 'HTTP/1.1 401 Unauthorized\r\n'
header: WWW-Authenticate: Basic
header: Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
header: X-Frame-Options: DENY
header: Pragma: no-cache
header: Cache-Control: no-Store,no-Cache
header: X-XSS-Protection: 1; mode=block
header: X-Content-Type-Options: nosniff
header: Content-Security-Policy: default-src 'none'; img-src 'self' data:; font-src 'self'; style-src 'self'; script-src 'self'; connect-src 'self' wss:; form-action 'none'; frame-ancestors 'none'; object-src 'none'; base-uri 'none'
header: Content-Type: application/json
header: Date: Tue, 05 Mar 2024 03:56:50 GMT
header: Connection: close
header: Content-Length: 829

@glimchb
Copy link
Member Author

glimchb commented Mar 5, 2024

found it!!!

header: Connection: keep-alive

vs

header: Connection: close

reproduces with simple:

$ curl -k -H "X-Auth-Token: IDY0mdVOxAyNhS1XzBoL" -H "Connection: close" -X GET https://10.246.87.133/redfish/v1/UpdateService

also checked the code https://github.com/python/cpython/blob/3.9/Lib/urllib/request.py#L1331

@jcastanos2
Copy link
Contributor

jcastanos2 commented Mar 5, 2024

OK, I think we have two issues: one is the unsecure_context I outlined before. Even when I run if with a valid token the first time, it fails with an exception. And, then, if I actually modify the community code to provide the unsecure_context in the urrlib_request.open, it works the first time and fails the second one (which is the close that Boris mentioned).
I distilled the ansible redfish module to something simple (see the attached python script):

get2.py.txt

``sancho@doca-vr-ansible:~/opi/ansible-opi-dpu/jgctests$ echo $token
ltSvFgT3VYyIk93YbVvF
sancho@doca-vr-ansible:~/opi/ansible-opi-dpu/jgctests$ python3 ./get2.py ltSvFgT3VYyIk93YbVvF
{'msg': 'URL Error on GET request to '
        "'https://10.137.189.246/redfish/v1/UpdateService': '[SSL: "
        'CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed '
        "certificate (_ssl.c:1007)'",
 'ret': False}
sancho@doca-vr-ansible:~/opi/ansible-opi-dpu/jgctests$ python3 ./get2.py -U ltSvFgT3VYyIk93YbVvF
{'data': {'@odata.id': '/redfish/v1/UpdateService',
          '@odata.type': '#UpdateService.v1_8_0.UpdateService',
          'Actions': {'#UpdateService.SimpleUpdate': {'[email protected]': [['SCP']],
                                                      'target': '/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate'},
                      'Oem': {'Nvidia': {'#NvidiaUpdateService.CommitImage': {'@Redfish.ActionInfo': '/redfish/v1/UpdateService/Oem/Nvidia/CommitImageActionInfo',
                                                                              'target': '/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.CommitImage'},
                                         '#NvidiaUpdateService.PublicKeyExchange': {'target': '/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.PublicKeyExchange'},
                                         '#NvidiaUpdateService.RevokeAllRemoteServerPublicKeys': {'target': '/redfish/v1/UpdateService/Actions/Oem/NvidiaUpdateService.RevokeAllRemoteServerPublicKeys'}}}},
          'Description': 'Service for Software Update',
          'FirmwareInventory': {'@odata.id': '/redfish/v1/UpdateService/FirmwareInventory'},
          'HttpPushUri': '/redfish/v1/UpdateService/update',
          'HttpPushUriOptions': {'HttpPushUriApplyTime': {'ApplyTime': 'OnReset'}},
          'HttpPushUriTargets': [],
          'Id': 'UpdateService',
          'MaxImageSizeBytes': 209715200,
          'MultipartHttpPushUri': '/redfish/v1/UpdateService/update-multipart',
          '[email protected]': {'@odata.type': '#Settings.v1_3_3.OperationApplyTimeSupport',
                                                                     'SupportedValues': ['Immediate']},
          'Name': 'Update Service',
          'ServiceEnabled': True,
          'SoftwareInventory': {'@odata.id': '/redfish/v1/UpdateService/SoftwareInventory'},
          'Status': {'Conditions': [], 'State': 'Enabled'}},
 'headers': {'allow': 'GET, PATCH, HEAD',
             'cache-control': 'no-Store,no-Cache',
             'connection': 'close',
             'content-length': '1821',
             'content-security-policy': "default-src 'none'; img-src 'self' "
                                        "data:; font-src 'self'; style-src "
                                        "'self'; script-src 'self'; "
                                        "connect-src 'self' wss:; form-action "
                                        "'none'; frame-ancestors 'none'; "
                                        "object-src 'none'; base-uri 'none'",
             'content-type': 'application/json',
             'date': 'Tue, 05 Mar 2024 19:42:20 GMT',
             'etag': '"2BB654F0"',
             'odata-version': '4.0',
             'pragma': 'no-cache',
             'strict-transport-security': 'max-age=31536000; '
                                          'includeSubdomains; preload',
             'x-content-type-options': 'nosniff',
             'x-frame-options': 'DENY',
             'x-xss-protection': '1; mode=block'},
 'resp': <http.client.HTTPResponse object at 0x7fdbad5dcb20>,
 'ret': True}
sancho@doca-vr-ansible:~/opi/ansible-opi-dpu/jgctests$ python3 ./get2.py -U ltSvFgT3VYyIk93YbVvF
{'msg': 'HTTP Error 401 on GET request to '
        "'https://10.137.189.246/redfish/v1/UpdateService', extended message: "
        "'While accessing the resource at '/redfish/v1/UpdateService', the "
        "service received an authorization error 'Invalid username or "
        "password'.'",
 'ret': False,
 'status': 401}

@glimchb
Copy link
Member Author

glimchb commented Mar 7, 2024

unsecure_context

I don't see an issue with unsecure_context in my environment. I will double-check again.
for mee looks like validate_certs is always false, so context should already be unverified
see https://github.com/ansible/ansible/blob/stable-2.16/lib/ansible/module_utils/urls.py#L1440

@glimchb glimchb added the bug Something isn't working label Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants