1*** Settings ***
2Documentation    Test certificate in OpenBMC.
3
4Resource         ../../lib/resource.robot
5Resource         ../../lib/bmc_redfish_resource.robot
6Resource         ../../lib/openbmc_ffdc.robot
7Resource         ../../lib/certificate_utils.robot
8Library          String
9
10Force Tags       Certificate_Test
11
12Suite Setup      Suite Setup Execution
13Test Teardown    Test Teardown Execution
14
15
16*** Variables ***
17
18${invalid_value}  abc
19${ROOT_CA_FILE_PATH}  /etc/ssl/certs/authority/*
20
21
22** Test Cases **
23
24Verify Server Certificate Replace
25    [Documentation]  Verify server certificate replace.
26    [Tags]  Verify_Server_Certificate_Replace
27    [Template]  Replace Certificate Via Redfish
28
29    # cert_type  cert_format                         expected_status
30    Server       Valid Certificate Valid Privatekey  ok
31    Server       Empty Certificate Valid Privatekey  error
32    Server       Valid Certificate Empty Privatekey  error
33    Server       Empty Certificate Empty Privatekey  error
34
35
36Verify Client Certificate Replace
37    [Documentation]  Verify client certificate replace.
38    [Tags]  Verify_Client_Certificate_Replace
39    [Template]  Replace Certificate Via Redfish
40
41    # cert_type  cert_format                         expected_status
42    Client       Valid Certificate Valid Privatekey  ok
43    Client       Empty Certificate Valid Privatekey  error
44    Client       Valid Certificate Empty Privatekey  error
45    Client       Empty Certificate Empty Privatekey  error
46
47
48Verify CA Certificate Replace
49    [Documentation]  Verify CA certificate replace.
50    [Tags]  Verify_CA_Certificate_Replace
51    [Template]  Replace Certificate Via Redfish
52
53    # cert_type  cert_format        expected_status
54    CA           Valid Certificate  ok
55    CA           Empty Certificate  error
56
57
58Verify Client Certificate Install
59    [Documentation]  Verify client certificate install.
60    [Tags]  Verify_Client_Certificate_Install
61    [Template]  Install And Verify Certificate Via Redfish
62
63    # cert_type  cert_format                         expected_status
64    Client       Valid Certificate Valid Privatekey  ok
65    Client       Empty Certificate Valid Privatekey  error
66    Client       Valid Certificate Empty Privatekey  error
67    Client       Empty Certificate Empty Privatekey  error
68
69
70Verify CA Certificate Install
71    [Documentation]  Verify CA certificate install.
72    [Tags]  Verify_CA_Certificate_Install
73    [Template]  Install And Verify Certificate Via Redfish
74
75    # cert_type  cert_format        expected_status
76    CA           Valid Certificate  ok
77    CA           Empty Certificate  error
78
79
80Verify Maximum CA Certificate Install
81    [Documentation]  Verify maximum CA certificate install.
82    [Tags]  Verify_Maximum_CA_Certificate_Install
83    [Teardown]  Run Keywords  FFDC On Test Case Fail  AND  Delete All CA Certificate Via Redfish
84
85    # Get CA certificate count from BMC.
86    redfish.Login
87    ${cert_list}=  Redfish_Utils.Get Member List  /redfish/v1/Managers/bmc/Truststore/Certificates
88    ${cert_count}=  Get Length  ${cert_list}
89
90    # Install CA certificate to reach maximum count of 10.
91    FOR  ${INDEX}  IN RANGE  ${cert_count}  10
92      Install And Verify Certificate Via Redfish  CA  Valid Certificate  ok  ${FALSE}
93      ${cert_count}=  Evaluate  ${cert_count} + 1
94    END
95
96    # Verify error while installing 11th CA certificate.
97    Install And Verify Certificate Via Redfish  CA  Valid Certificate  error  ${FALSE}
98
99
100Verify Server Certificate View Via Openssl
101    [Documentation]  Verify server certificate via openssl command.
102    [Tags]  Verify_Server_Certificate_View_Via_Openssl
103
104    redfish.Login
105
106    ${cert_file_path}=  Generate Certificate File Via Openssl  Valid Certificate Valid Privatekey
107    ${bytes}=  OperatingSystem.Get Binary File  ${cert_file_path}
108    ${file_data}=  Decode Bytes To String  ${bytes}  UTF-8
109
110    ${certificate_dict}=  Create Dictionary
111    ...  @odata.id=/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1
112    ${payload}=  Create Dictionary  CertificateString=${file_data}
113    ...  CertificateType=PEM  CertificateUri=${certificate_dict}
114
115    ${resp}=  redfish.Post  /redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate
116    ...  body=${payload}
117
118    Wait Until Keyword Succeeds  2 mins  15 secs  Verify Certificate Visible Via OpenSSL  ${cert_file_path}
119
120
121Verify CSR Generation For Server Certificate
122    [Documentation]  Verify CSR generation for server certificate.
123    [Tags]  Verify_CSR_Generation_For_Server_Certificate
124    [Template]  Generate CSR Via Redfish
125
126    # csr_type  key_pair_algorithm  key_bit_length  key_curv_id  expected_status
127    Server      RSA                 ${2048}         ${EMPTY}     ok
128    Server      EC                  ${EMPTY}        prime256v1   ok
129    Server      EC                  ${EMPTY}        secp521r1    ok
130    Server      EC                  ${EMPTY}        secp384r1    ok
131
132
133Verify CSR Generation For Client Certificate
134    [Documentation]  Verify CSR generation for client certificate.
135    [Tags]  Verify_CSR_Generation_For_Client_Certificate
136    [Template]  Generate CSR Via Redfish
137
138    # csr_type  key_pair_algorithm  key_bit_length  key_curv_id  expected_status
139    Client      RSA                 ${2048}         ${EMPTY}     ok
140    Client      EC                  ${EMPTY}        prime256v1   ok
141    Client      EC                  ${EMPTY}        secp521r1    ok
142    Client      EC                  ${EMPTY}        secp384r1    ok
143
144
145Verify CSR Generation For Server Certificate With Invalid Value
146    [Documentation]  Verify error while generating CSR for server certificate with invalid value.
147    [Tags]  Verify_CSR_Generation_For_Server_Certificate_With_Invalid_Value
148    [Template]  Generate CSR Via Redfish
149
150    # csr_type  key_pair_algorithm  key_bit_length    key_curv_id       expected_status
151    Server      ${invalid_value}    ${2048}           prime256v1        error
152    Server      RAS                 ${invalid_value}  ${EMPTY}          error
153    Server      EC                  ${EMPTY}          ${invalid_value}  error
154
155
156Verify CSR Generation For Client Certificate With Invalid Value
157    [Documentation]  Verify error while generating CSR for client certificate with invalid value.
158    [Tags]  Verify_CSR_Generation_For_Client_Certificate_With_Invalid_Value
159    [Template]  Generate CSR Via Redfish
160
161    Client      ${invalid_value}    ${2048}           prime256v1        error
162    Client      RSA                 ${invalid_value}  ${EMPTY}          error
163    Client      EC                  ${EMPTY}          ${invalid_value}  error
164
165
166*** Keywords ***
167
168Install And Verify Certificate Via Redfish
169    [Documentation]  Install and verify certificate using Redfish.
170    [Arguments]  ${cert_type}  ${cert_format}  ${expected_status}  ${delete_cert}=${True}
171
172    # Description of argument(s):
173    # cert_type           Certificate type (e.g. "Client" or "CA").
174    # cert_format         Certificate file format
175    #                     (e.g. "Valid_Certificate_Valid_Privatekey").
176    # expected_status     Expected status of certificate replace Redfish
177    #                     request (i.e. "ok" or "error").
178    # delete_cert         Certificate will be deleted before installing if this True.
179
180    redfish.Login
181    Run Keyword If  '${cert_type}' == 'CA' and '${delete_cert}' == '${True}'
182    ...  Delete All CA Certificate Via Redfish
183    ...  ELSE IF  '${cert_type}' == 'Client' and '${delete_cert}' == '${True}'
184    ...  Delete Certificate Via BMC CLI  ${cert_type}
185
186    ${time}=  Set Variable If  '${cert_format}' == 'Expired Certificate'  -10  365
187    ${cert_file_path}=  Generate Certificate File Via Openssl  ${cert_format}  ${time}
188    ${bytes}=  OperatingSystem.Get Binary File  ${cert_file_path}
189    ${file_data}=  Decode Bytes To String  ${bytes}  UTF-8
190
191    ${certificate_uri}=  Set Variable If
192    ...  '${cert_type}' == 'Client'  ${REDFISH_LDAP_CERTIFICATE_URI}
193    ...  '${cert_type}' == 'CA'  ${REDFISH_CA_CERTIFICATE_URI}
194
195    ${cert_id}=  Install Certificate File On BMC  ${certificate_uri}  ${expected_status}  data=${file_data}
196    Logging  Installed certificate id: ${cert_id}
197
198    # Adding delay after certificate installation.
199    Sleep  30s
200
201    ${cert_file_content}=  OperatingSystem.Get File  ${cert_file_path}
202    ${bmc_cert_content}=  Run Keyword If  '${expected_status}' == 'ok'  redfish_utils.Get Attribute
203    ...  ${certificate_uri}/${cert_id}  CertificateString
204
205    Run Keyword If  '${expected_status}' == 'ok'  Should Contain  ${cert_file_content}  ${bmc_cert_content}
206    [Return]  ${cert_id}
207
208
209Install Certificate File On BMC
210    [Documentation]  Install certificate file in BMC using POST operation.
211    [Arguments]  ${uri}  ${status}=ok  &{kwargs}
212
213    # Description of argument(s):
214    # uri         URI for installing certificate file via REST
215    #             e.g. "/xyz/openbmc_project/certs/server/https".
216    # status      Expected status of certificate installation via REST
217    #             e.g. error, ok.
218    # kwargs      A dictionary of keys/values to be passed directly to
219    #             POST Request.
220
221    Initialize OpenBMC  quiet=${quiet}
222
223    ${headers}=  Create Dictionary  Content-Type=application/octet-stream
224    ...  X-Auth-Token=${XAUTH_TOKEN}
225    Set To Dictionary  ${kwargs}  headers  ${headers}
226
227    ${ret}=  Post Request  openbmc  ${uri}  &{kwargs}
228    ${content_json}=  To JSON  ${ret.content}
229    ${cert_id}=  Set Variable If  '${ret.status_code}' == '${HTTP_OK}'  ${content_json["Id"]}  -1
230
231    Run Keyword If  '${status}' == 'ok'
232    ...  Should Be Equal As Strings  ${ret.status_code}  ${HTTP_OK}
233    ...  ELSE IF  '${status}' == 'error'
234    ...  Should Be Equal As Strings  ${ret.status_code}  ${HTTP_INTERNAL_SERVER_ERROR}
235
236    Delete All Sessions
237
238    [Return]  ${cert_id}
239
240Replace Certificate Via Redfish
241    [Documentation]  Test 'replace certificate' operation in the BMC via Redfish.
242    [Arguments]  ${cert_type}  ${cert_format}  ${expected_status}
243
244    # Description of argument(s):
245    # cert_type           Certificate type (e.g. "Server" or "Client").
246    # cert_format         Certificate file format
247    #                     (e.g. Valid_Certificate_Valid_Privatekey).
248    # expected_status     Expected status of certificate replace Redfish
249    #                     request (i.e. "ok" or "error").
250
251    # Install certificate before replacing client or CA certificate.
252    ${cert_id}=  Run Keyword If  '${cert_type}' == 'Client'
253    ...    Install And Verify Certificate Via Redfish  ${cert_type}  Valid Certificate Valid Privatekey  ok
254    ...  ELSE IF  '${cert_type}' == 'CA'
255    ...    Install And Verify Certificate Via Redfish  ${cert_type}  Valid Certificate  ok
256
257    redfish.Login
258
259    ${time}=  Set Variable If  '${cert_format}' == 'Expired Certificate'  -10  365
260    ${cert_file_path}=  Generate Certificate File Via Openssl  ${cert_format}  ${time}
261
262    ${bytes}=  OperatingSystem.Get Binary File  ${cert_file_path}
263    ${file_data}=  Decode Bytes To String  ${bytes}  UTF-8
264
265    ${certificate_uri}=  Set Variable If
266    ...  '${cert_type}' == 'Server'  ${REDFISH_HTTPS_CERTIFICATE_URI}/1
267    ...  '${cert_type}' == 'Client'  ${REDFISH_LDAP_CERTIFICATE_URI}/1
268    ...  '${cert_type}' == 'CA'  ${REDFISH_CA_CERTIFICATE_URI}/${cert_id}
269
270    ${certificate_dict}=  Create Dictionary  @odata.id=${certificate_uri}
271    ${payload}=  Create Dictionary  CertificateString=${file_data}
272    ...  CertificateType=PEM  CertificateUri=${certificate_dict}
273
274    ${expected_resp}=  Set Variable If  '${expected_status}' == 'ok'  ${HTTP_OK}
275    ...  '${expected_status}' == 'error'  ${HTTP_NOT_FOUND}, ${HTTP_INTERNAL_SERVER_ERROR}
276    ${resp}=  redfish.Post  /redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate
277    ...  body=${payload}  valid_status_codes=[${expected_resp}]
278
279    ${cert_file_content}=  OperatingSystem.Get File  ${cert_file_path}
280    ${bmc_cert_content}=  redfish_utils.Get Attribute  ${certificate_uri}  CertificateString
281
282    Run Keyword If  '${expected_status}' == 'ok'
283    ...    Should Contain  ${cert_file_content}  ${bmc_cert_content}
284    ...  ELSE
285    ...    Should Not Contain  ${cert_file_content}  ${bmc_cert_content}
286
287
288Generate CSR Via Redfish
289    [Documentation]  Generate CSR using Redfish.
290    [Arguments]  ${cert_type}  ${key_pair_algorithm}  ${key_bit_length}  ${key_curv_id}  ${expected_status}
291
292    # Description of argument(s):
293    # cert_type           Certificate type ("Server" or "Client").
294    # key_pair_algorithm  CSR key pair algorithm ("EC" or "RSA")
295    # key_bit_length      CSR key bit length ("2048").
296    # key_curv_id         CSR key curv id ("prime256v1" or "secp521r1" or "secp384r1").
297    # expected_status     Expected status of certificate replace Redfish
298    #                     request ("ok" or "error").
299
300    redfish.Login
301
302    ${certificate_uri}=  Set Variable If
303    ...  '${cert_type}' == 'Server'  ${REDFISH_HTTPS_CERTIFICATE_URI}/
304    ...  '${cert_type}' == 'Client'  ${REDFISH_LDAP_CERTIFICATE_URI}/
305
306    ${certificate_dict}=  Create Dictionary  @odata.id=${certificate_uri}
307    ${payload}=  Create Dictionary  City=Austin  CertificateCollection=${certificate_dict}
308    ...  CommonName=${OPENBMC_HOST}  Country=US  Organization=IBM
309    ...  OrganizationalUnit=ISL  State=AU  KeyBitLength=${key_bit_length}
310    ...  KeyPairAlgorithm=${key_pair_algorithm}  KeyCurveId=${key_curv_id}
311
312    # Remove not applicable field for CSR generation.
313    Run Keyword If  '${key_pair_algorithm}' == 'EC'  Remove From Dictionary  ${payload}  KeyBitLength
314    ...  ELSE IF  '${key_pair_algorithm}' == 'RSA'  Remove From Dictionary  ${payload}  KeyCurveId
315
316    ${expected_resp}=  Set Variable If  '${expected_status}' == 'ok'  ${HTTP_OK}
317    ...  '${expected_status}' == 'error'  ${HTTP_INTERNAL_SERVER_ERROR}, ${HTTP_BAD_REQUEST}
318    ${resp}=  redfish.Post  /redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR
319    ...  body=${payload}  valid_status_codes=[${expected_resp}]
320
321    # Delay added between two CSR generation request.
322    Sleep  5s
323
324
325Delete Certificate Via BMC CLI
326    [Documentation]  Delete certificate via BMC CLI.
327    [Arguments]  ${cert_type}
328
329    # Description of argument(s):
330    # cert_type           Certificate type (e.g. "Client" or "CA").
331
332    ${certificate_file_path}  ${certificate_service}  ${certificate_uri}=
333    ...  Run Keyword If  '${cert_type}' == 'Client'
334    ...    Set Variable  /etc/nslcd/certs/cert.pem  phosphor-certificate-manager@nslcd.service
335    ...    ${REDFISH_LDAP_CERTIFICATE_URI}
336    ...  ELSE IF  '${cert_type}' == 'CA'
337    ...    Set Variable  ${ROOT_CA_FILE_PATH}  phosphor-certificate-manager@authority.service
338    ...    ${REDFISH_CA_CERTIFICATE_URI}
339
340    ${file_status}  ${stderr}  ${rc}=  BMC Execute Command
341    ...  [ -f ${certificate_file_path} ] && echo "Found" || echo "Not Found"
342
343    Return From Keyword If  "${file_status}" != "Found"
344    BMC Execute Command  rm ${certificate_file_path}
345    BMC Execute Command  systemctl restart ${certificate_service}
346    BMC Execute Command  systemctl daemon-reload
347    Wait Until Keyword Succeeds  1 min  10 sec  Redfish.Get  ${certificate_uri}/1
348    ...  valid_status_codes=[${HTTP_NOT_FOUND}, ${HTTP_INTERNAL_SERVER_ERROR}]
349
350
351Delete All CA Certificate Via Redfish
352    [Documentation]  Delete all CA certificate via Redfish.
353
354    ${cert_list}=  Redfish_Utils.Get Member List  /redfish/v1/Managers/bmc/Truststore/Certificates
355    FOR  ${cert}  IN  @{cert_list}
356      Redfish.Delete  ${cert}  valid_status_codes=[${HTTP_NO_CONTENT}]
357    END
358
359
360Suite Setup Execution
361    [Documentation]  Do suite setup tasks.
362
363    # Create certificate sub-directory in current working directory.
364    Create Directory  certificate_dir
365
366
367Test Teardown Execution
368    [Documentation]  Do the post test teardown.
369
370    FFDC On Test Case Fail
371    redfish.Logout
372