Case 3: Vanilla Foreman with registration done through proxy
sequenceDiagram
autonumber
Participant Foreman
Participant Proxy
Participant Client
Client->>Proxy: GET $proxy_url/register
Proxy->>Foreman: GET $foreman_url/register?url=$proxy_url
Foreman->>Proxy: GRT containing curl -X POST $proxy_url/register | sh
Proxy->>Client: GRT containing curl -X POST $proxy_url/register | sh
Client->>Proxy: POST $proxy_url/register
Proxy->>Foreman: POST $foreman_url/register?url=$proxy_url
Foreman->>Proxy: HRT with curl $proxy_url/built
Proxy->>Client: HRT with curl $proxy_url/built
Client->>Proxy: POST $proxy_url/built
Proxy->>Foreman: POST $foreman_url/built
Steps in more details
- client contacts the proxy to initiate the process.
- proxy’s registration module computes proxy’s url based on the incoming request (more details later). It contacts Foreman at the $foreman_url based on the foreman_url proxy setting. Besides forwarding all parameters and headers client sent in request 1, it also adds url parameter.
- Foreman realizes that custom url was passed, so instead of using $foreman_url, it generates HRT curl with the hostname being a value of url parameter. For example if the client called
https://proxy.example.com:8443/register
, Foreman will receivehttps://proxy.example.com:8443
as url and inside of GRT, it will rendercurl -X POST https://proxy.example.com:8443/register
. - client gets the GRT and executes it, once it hits the HRT request, it continues with step 5
- proxy does the same as in step 3, forwards the request to Foreman, but tells it to use a different url for additional requests
- Foreman registers the host and renders HRT for it, again using
params[:url] || foreman_url('built')
logic, resulting in HRT which will call home through proxy. - HRT template makes it to the proxy
- HRT template makes it to the client
- standard proxying of informing about host being built, no url magic needed here
- Foreman turns host into built, hooray
How proxy determines $proxy_url in steps 2 and 6?
Proxy looks at request.env['REQUEST_URI']
which contains the URL that client used in order to contact the proxy. In some edge cases, it may not be hostname -f
of the proxy. It may not be the url of the proxy in Foreman. But it’s something we know client can resolve and talk to. The whole logic is request.env['REQUEST_URI']&.split('/register')&.first
meaning we still keep the information about scheme, fqdn and port that was used.
Authentication of requests
GRT contains JWT that’s used to authenticate the request in step 5. Given it’s passed as a custom header, it gets automatically proxied in step 6. Foreman verifies the signature.
HRT contains the build token that is used to authenticate the POST /built
after the execution of HRT is done. Please don’t ask for replacing this with JWT in Foreman 2.3
Authorization
JWT is tied to the user account, so HRT rendering happens under that account permissions. The fact the user knows build token means he had the permission to created (register) the host. We trust he or she can switch this flag without proper authorization. This is the well known concept from provisioning, where token knowledge is enough to flip the build mode.
I hope this helps, questions please. Also once you’re happy with the design for case 3, ACK would be great at least from the same group.