OAuth for MyProxy GetProxy Endpoint
OAuth for MyProxy (OA4MP) is based around the OIDC/OA4MP Protocol, which is a modified version of OpenID Connect. The modifications introduced by OA4MP include the GetCert Endpoint which is used by the OA4MP Client (ex. Science Gateway) to retrieve an End Entity Certificate (EEC) on behalf of the authenticated user. In certain scenarios the use of EECs can be replaced by Proxy Certificates. Proxy Certificates, usually having a shorter lifetime than EECs, are less likely to be used maliciously given their short validity period, while still conveying the same authentication information as an EEC would. Moreover, a Proxy Certificate can contain additional authorization information in the form of VOMS Extensions.
We propose adding a GetProxy Endpoint into the OIDC/OA4MP Protocol, which returns Proxy Certificates. The main differences between the GetProxy and GetCert Endpoint are:
- returns Proxy Certificates
- generates CSR on server side instead of client side
- accepts VONAME and VOMSES parameters
The GetProxy Endpoint, just like the GetCert Endpoint is an OAuth2.0 protected resource that returns a proxy certificate. This proxy certificate consists of a certificate chain and private key of the proxy. The request made to the GetProxy Endpoint is made up of the following parameters:
|client_id||REQUIRED||The client identifier issued at registration time.|
|client_secret||REQUIRED||The client secret issued at registration time.|
|access_token||REQUIRED||OIDC (OAuth 2.0) access token obtained with token request. Provided in “Authorization: Bearer” header or as form value.|
|proxylifetime||OPTIONAL||Requested proxy lifetime (in seconds). In case this value exceeds the server side default, the request parameter is ignored.|
|voname||OPTIONAL||Specifies one or more VO to connect to for membership information. The VO name can be followed by additional group and role request. (see 'man voms-proxy-init' under -voms)|
|vomses||OPTIONAL||Specifies VOMS server information under 'vomses' file format|
Just like in case of GetCert, the access_token, client_id and client_secret parameters are there to ensure the authenticity of the request. Note that the 'certreq' parameter, containing the Certificate Signing Request (CSR), is no longer sent along in the request. Instead, a new keypair and CSR are created on the server side and used in the subsequent MyProxy GET request. The motivation behind this change is to take the burden of key generation off the OA4MP Client, thus making it more lighweight and easily adaptable by different communities.
Requesting a VOMS Proxy Certificate can be done by using the 'voname' and 'vomses' request parameters. These parameters are passed as they are to the subsequent MyProxy GET request.
Note: The VOMSES string is useful in scenarios where the user would like to get membership information from a VOMS server which is not configured in the backend MyProxy Server 'vomses' file.
POST /getproxy HTTP/1.1 Host: myproxy.example.edu Content-Type: application/x-www-form-urlencoded client_id=s6BhdRkqt3&client_secret=some_secret12345&access_token=8xLOxBtZp8&proxylifetime=43200& voname=superscience&vomses=%22testvo%22%20%22voms.example.edu%22%20%2215000%22%20%22%2FC%3DXX%2FO%3DExample%2FCN%3Dmyproxy.example.edu%22%20%22testvo%22
curl --capath /etc/grid-security/certificates/ -H "Host: myproxy.example.edu" -H "Content-Type: application/x-www-form-urlencoded" -X POST -d \ 'client_id=s6BhdRkqt3&client_secret=some_secret12345&access_token=8xLOxBtZp8&proxylifetime=43200& voname=superscience&vomses="testvo" "voms.example.edu" "15000" "/C=XX/O=Example/CN=myproxy.example.edu" "testvo"' \ https://myproxy.example.edu/oauth2/getproxy
In case of a successful request the body of the response message contains the Proxy Certificate in PEM format. The first certificate in the chain is the proxy followed by its private key, and the rest of the chain.
HTTP/1.1 200 OK Content-Type: text/plain -----BEGIN CERTIFICATE----- MIIJ+DCCCOCgAwIBAgIEWVmVpjANBgkqhkiG9w0BAQsFADBVMQ0wCwYDVQQKEwRHcmlkMRMwEQYD VQQLEwpHbG9idXNUZXN0MRwwGgYDVQQDFhNkdW1teUBteS1kb21haW4uY29tMREwDwYDVQQDEwg3 ... BvjdU/+9xSlBnFm7v2thFcqienTP6cY/iCQPDzT9wv/fdv/DToy9oN0BrtYievZjZOLcjsczMD5M KXOr/StOe+qDtT6CXwpzGNE4QJYTl8yoQguZaSsGxgP2PDPS0G0dLGTv8YvG3Fle -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCAIZ9nkUddKLznkHuda9yRxPP5 j2JO9U0CFmr4EmKjvza8BstyndksT235zODXIs3wVVYqxxMqH4J9181MlCxs8f7GXRlgDlY3oSa/ ... eM7xUIqehh+Yy01oKEcSNE3ykvySXxp7JBvREhNCaObxpMhi0JAMaAJ0atf9e8E/DFOccy6P9McZ ysKQufEOgePsck/OrFEDmGqs+bA= -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDQjCCAiygAwIBAgIEBE72YDALBgkqhkiG9w0BAQswQjENMAsGA1UEChMER3JpZDETMBEGA1UE CxMKR2xvYnVzVGVzdDEcMBoGA1UEAxYTZHVtbXlAbXktZG9tYWluLmNvbTAeFw0xNjAxMDYxNTAx ... XZxr1zbbcPnol8vETpTiRvW3I8ms3PBwgWXE4xIbN8Myng7UgPjasv+JOykx+3UIVD1FblZAXdnH fBJa7cu/xGomko+7i0opoQewaRcPLmGbL6xVuW3MERwIPfiKqsz+4w== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICnjCCAgegAwIBAgICAMEwDQYJKoZIhvcNAQELBQAwTzENMAsGA1UEChMER3JpZDETMBEGA1UE CxMKR2xvYnVzVGVzdDEpMCcGA1UEAxMgR2xvYnVzIFNpbXBsZSBDQSBmb3IgRGVtbyBQb3J0YWww ... IACngeT/1vXoC/2s03B9dwK4s/pBs7EVG/9kf5Wlew3IVwtcqTI2kDXUPiLey+ro37Qct5htseft E2TwLFzbCOo9wI/6cCu7uSOyxGwVlk+rvTfJFsaAmYOMeQuytQCTRy9loFNz6Hk= -----END CERTIFICATE-----
Example client code
For example code, see this simple PHP script, which shows how the /getproxy endpoint can be used to obtain a valid proxy certificate.
The implementation of the GetProxy Endpoint has been separated from the Master Portal OA4MP extension because it was found to be much easier to modify existing OA4MP code than to extend it. This basically means that for the purpose of implementing this endpoint we forked OA4MP. This custom OA4MP having the GetProxy Endpoint implemented can be found under the myproxy-fork and ncsas-security-all-fork projects. The separation of the two codebases is inherited from the original OA4MP implementation.
The OA4MP Client has to be able to distinguish between cases of requesting an EEC through GetCert and requesting a proxy through GetProxy, since the backend Server is configured to provide one OR the other (EEC or Proxy), not both. This is done with the use of a new OA4MP Client configuration parameter called 'requestProxies'.
|requestProxies||N||false||Enables making requests to the GetProxy Endpoint|
<client name="client-config" address="https://portal.example.edu/portal"> ... <requestProxies>true</requestProxies> ... </client>
By setting this configuration to true a GetProxy Endpoint aware OA2MPProxyService object will be returned to client servlets instead of a OA2MPService object. The servlet can then request a proxy by calling the getProxy(OA2Asset a, ATResponse2 atResponse2) method of the returned object. The GetProxy request is build internally using the clients' ID, secret and the current transactions' access token. User input (voname and vomses) should be provided to this method via the OA2Asset parameter. The proxylifetime parameter is taken from the 'lifetime' client configuration.
The OA4MP Server has both GetCert and GetProxy Endpoints available at the same time, but the MyProxy Server in its backend can only be configured to return either EEC or Proxy Certificate.
Note: Do NOT use the GetProxy Endpoint when the backend MyProxy Server is configured in CA mode issuing End Entity Certificates! You will end up receiving EEC from the GetProxy Endpoint.
The implementation of the GetProxy servlet is done in OA2ProxyServlet. A successful GetProxy request will execute the following flow in the servlet:
- Step 1 : As mentioned above, the key and CSR generation has been moved away from the OA4MP Client into the Server. The verifyAndGet method creates a new keypair and saves the resulting private key and CSR into the transaction. The proxylifetime, voname and vomses are stripped off from the request and saved in the transaction.
- Step 2 : The checkMPConnection method initiates a new MyProxy connection
- Step 3 : The getX509Certificates method inserts the proxylifetime, voname and vomses values into the MyProxy connection after which proceeds to execute a MyProxy GET command, returning the certificate chain created.
- Step 4 : The preprocess method is called before the resulting certificate chain is written out into the response buffer. Here, the MyX509Certificates holding only the certificate chain is swapped out to a MyX509Proxy object containing the same certificate chain, together with the private key from the transaction (saved in Step 1).
The myproxy project builds on top of the ncsa.security.all project, and therefore some of the modified code logically belongs into this project.
The original OA4MP uses MyX509Certificates as a container to transmit and receive certificate chains. With the extension of GetProxy Endpoint, this container class is no longer sufficient to transmit proxies around, because it cannot hold the proxy's private key. A new container under the name of MyX509Proxy has been implemented which extends MyX509Certificates.
The ProxyUtil class holds a set of static methods used for proxy transformation and generation. This class works with the aid of a newly introduced dependency: canl-java. At the time of this writing the canl version integrated was version 2.2.0.
A new request server called PPServer2 (Protected Proxy Server 2) has been added after the model of PAServer2 used for GetCert Requests. The new PPServer2 class sets GetProxy request parameters and creates a MyX509Proxy out of the response.