Chapter 2. Authentication and Security
Chapter 2. Authentication and Security 2.1. TLS/SSL Certification The Red Hat Virtualization API requires Hypertext Transfer Protocol Secure (HTTPS) [1] for secure interaction with client software, such as the SDK and CLI components. This involves obtaining the CA certificate used by the server, and importing it into the certificate store of your client. 2.1.1. Obtaining the CA Certificate You can obtain the CA certificate from the Red Hat Virtualization Manager and transfer it to the client machine using one of these methods: Method 1 The preferred method for obtaining the CA certificate is to use the openssl s_client command line tool to perform a real TLS handshake with the server, and then extract the certificates that it presents. Run a command like this: This command will connect to the server and display output similar to the following: The text between the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- marks shows the certificates presented by the server. The first one is the certificate of the server itself, and the last one is the certificate of the CA. Copy the CA certificate, including the marks, to the ca.crt file. The result should look like this: Important This is the most reliable method to obtain the CA certificate used by the server. The rest of the methods described here will work in most cases, but they will not obtain the correct CA certificate if it has been manually replaced by the administrator of the server. Method 2 If you cannot use the openssl s_client method described above, you can instead use a command line tool to download the CA certificate from the Red Hat Virtualization Manager. Examples of command line tools include curl and wget , both of which are available on multiple platforms. If using curl : If using wget : Method 3 Use a web browser to navigate to the certificate located at: Depending on the chosen browser, the certificate either downloads or imports into the browser's keystore. If the browser downloads the certificate : save the file as ca.crt . If the browser imports the certificate : export it from the browser's certification options and save it as ca.crt . Method 4 Log in to the Red Hat Virtualization Manager, export the certificate from the truststore, and copy it to your client machine. Log in to the Red Hat Virtualization Manager machine as root . Export the certificate from the truststore using the Java keytool management utility: This creates a certificate file called ca.crt . Copy the certificate to the client machine using the scp command: Each of these methods results in a certificate file named ca.crt on your client machine. You must then import this file into the certificate store of the client. 2.1.2. Importing a Certificate to a Client Importing a certificate to a client relies on how the client stores and interprets certificates. See your client documentation for more information on importing a certificate. 2.2. Authentication Any user with a Red Hat Virtualization Manager account has access to the API. All requests must be authenticated using either OAuth or basic authentication, as described below. 2.2.1. OAuth Authentication Since version 4.0 of Red Hat Virtualization the preferred authentication mechanism is OAuth 2.0 , as described in RFC 6749 . OAuth is a sophisticated protocol, with several mechanisms for obtaining authorization and access tokens. For use with the Red Hat Virtualization API, the only supported one is the Resource Owner Password Credentials Grant , as described in section 4.3 of RFC 6749. You must first obtain a token , sending the user name and password to the Red Hat Virtualization Manager single sign-on service: The request body must contain the grant_type , scope , username , and password parameters: Table 2.1. OAuth token request parameters Name Value grant_type password scope ovirt-app-api username admin@internal password mypassword These parameters must be URL-encoded . For example, the @ character in the user name needs to be encoded as %40 . The resulting request body will be something like this: Important The scope parameter is described as optional in the OAuth RFC, but when using it with the Red Hat Virtualization API it is mandatory, and its value must be ovirt-app-api . If the user name and password are valid, the Red Hat Virtualization Manager single sign-on service will respond with a JSON document similar to this one: For API authentication purposes, the only relevant name/value pair is the access_token . Do not manipulate this in any way; use it exactly as provided by the SSO service. Once the token has been obtained, it can be used to perform requests to the API by including it in the HTTP Authorization header, and using the Bearer scheme. For example, to get the list of virtual machines, send a request like this: The token can be used multiple times, for multiple requests, but it will eventually expire. When it expires, the server will reject the request with the 401 HTTP response code: When this happens, a new token is needed, as the Red Hat Virtualization Manager single sign-on service does not currently support refreshing tokens. A new token can be requested using the same method described above. 2.2.2. Basic Authentication Important Basic authentication is supported only for backwards compatibility; it is deprecated since version 4.0 of Red Hat Virtualization, and will be removed in the future. Each request uses HTTP Basic Authentication [2] to encode the credentials. If a request does not include an appropriate Authorization header, the server sends a 401 Authorization Required response: Request are issued with an Authorization header for the specified realm. Encode an appropriate Red Hat Virtualization Manager domain and user in the supplied credentials with the username@domain:password convention. The following table shows the process for encoding credentials in Base64 . Table 2.2. Encoding credentials for API access Item Value User name admin Domain internal Password mypassword Unencoded credentials admin@internal:mypassword Base64 encoded credentials YWRtaW5AaW50ZXJuYWw6bXlwYXNzd29yZA== Provide the Base64-encoded credentials as shown: Important Basic authentication involves potentially sensitive information, such as passwords, sent as plain text. The API requires Hypertext Transfer Protocol Secure (HTTPS) for transport-level encryption of plain-text requests. Important Some Base64 libraries break the result into multiple lines and terminate each line with a newline character. This breaks the header and causes a faulty request. The Authorization header requires the encoded credentials on a single line within the header. 2.2.3. Authentication Sessions The API also provides authentication session support. Send an initial request with authentication details, then send all subsequent requests using a session cookie to authenticate. 2.2.3.1. Requesting an Authenticated Session Send a request with the Authorization and Prefer: persistent-auth headers: This returns a response with the following header: Take note of the JSESSIONID= value. In this example the value is 5dQja5ubr4yvI2MM2z+LZxrK . Send all subsequent requests with the Prefer: persistent-auth and Cookie headers with the JSESSIONID= value. The Authorization header is no longer needed when using an authenticated session. When the session is no longer required, perform a request to the sever without the Prefer: persistent-auth header. [1] HTTPS is described in RFC 2818 HTTP Over TLS. [2] Basic Authentication is described in RFC 2617 HTTP Authentication: Basic and Digest Access Authentication .
openssl s_client -connect myengine.example.com:443 -showcerts < /dev/null CONNECTED(00000003) depth=1 C = US, O = Example Inc., CN = myengine.example.com.23416 verify error:num=19:self signed certificate in certificate chain --- Certificate chain 0 s:/C=US/O=Example Inc./CN=myengine.example.com i:/C=US/O=Example Inc./CN=myengine.example.com.23416 -----BEGIN CERTIFICATE----- MIIEaTCCA1GgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMx FTATBgNVBAoTDEV4YW1wbGUgSW5jLjEjMCEGA1UEAxMaZW5naW5lNDEuZXhhbXBs SVlJe7e5FTEtHJGTAeWWM6dGbsFhip5VXM0gfqg= -----END CERTIFICATE----- 1 s:/C=US/O=Example Inc./CN=myengine.example.com.23416 i:/C=US/O=Example Inc./CN=myengine.example.com.23416 -----BEGIN CERTIFICATE----- MIIDxjCCAq6gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMx FTATBgNVBAoTDEV4YW1wbGUgSW5jLjEjMCEGA1UEAxMaZW5naW5lNDEuZXhhbXBs Pkyg1rQHR6ebGQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDxjCCAq6gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMx FTATBgNVBAoTDEV4YW1wbGUgSW5jLjEjMCEGA1UEAxMaZW5naW5lNDEuZXhhbXBs Pkyg1rQHR6ebGQ== -----END CERTIFICATE----- curl --output ca.crt 'http://myengine.example.com/ovirt-engine/services/pki-resource?resource=ca-certificate&format=X509-PEM-CA' wget --output-document ca.crt 'http://myengine.example.com/ovirt-engine/services/pki-resource?resource=ca-certificate&format=X509-PEM-CA' https://myengine.example.com/ovirt-engine/services/pki-resource?resource=ca-certificate&format=X509-PEM-CA keytool -keystore /etc/pki/ovirt-engine/.truststore -storepass mypass -exportcert -alias cacert -rfc -file ca.crt scp ca.crt myuser@myclient.example.com:/home/myuser/. POST /ovirt-engine/sso/oauth/token HTTP/1.1 Host: myengine.example.com Content-Type: application/x-www-form-urlencoded Accept: application/json grant_type=password&scope=ovirt-app-api&username=admin%40internal&password=mypassword { "access_token": "fqbR1ftzh8wBCviLxJcYuV5oSDI=", "token_type": "bearer", "scope": "...", } GET /ovirt-engine/api/vms HTTP/1.1 Host: myengine.example.com Accept: application/xml Authorization: Bearer fqbR1ftzh8wBCviLxJcYuV5oSDI= HTTP/1.1 401 Unauthorized HEAD /ovirt-engine/api HTTP/1.1 Host: myengine.example.com HTTP/1.1 401 Authorization Required HEAD /ovirt-engine/api HTTP/1.1 Host: myengine.example.com Authorization: Basic YWRtaW5AaW50ZXJuYWw6bXlwYXNzd29yZA== HTTP/1.1 200 OK HEAD /ovirt-engine/api HTTP/1.1 Host: myengine.example.com Authorization: Basic YWRtaW5AaW50ZXJuYWw6bXlwYXNzd29yZA== Prefer: persistent-auth HTTP/1.1 200 OK Set-Cookie: JSESSIONID=5dQja5ubr4yvI2MM2z+LZxrK; Path=/ovirt-engine/api; Secure HEAD /ovirt-engine/api HTTP/1.1 Host: myengine.example.com Prefer: persistent-auth Cookie: JSESSIONID=5dQja5ubr4yvI2MM2z+LZxrK HTTP/1.1 200 OK HEAD /ovirt-engine/api HTTP/1.1 Host: myengine.example.com Authorization: Basic YWRtaW5AaW50ZXJuYWw6bXlwYXNzd29yZA== HTTP/1.1 200 OK