Advanced Programmatic Provisioning
This appendix provides further context around the programmatic bootstrapping of the initial administrator account on a fresh Posit Connect instance.
More specifically, this appendix supports users who are utilizing custom client tooling instead of using the Json Web Token (JWT) request implementation provided by rsconnect-python
. The rsconnect-python
implementation is the recommended approach for most use cases and is described in the core programmatic provisioning section of the admin guide.
Rationale
Under typical operation, many of the provisioning endpoints in Posit Connect require user authentication. Posit Connect assumes that most of the provisioning work will be performed by an admin-scoped user account with a provisioned API key.
This creates a circular dependency on a fresh Posit Connect installation with no users. There are no user accounts, and therefore, there are no user-associated API keys that can provide access to relevant provisioning endpoints.
To break this circular dependency, Posit Connect provides a bootstrapping endpoint that accepts a JSON Web Token (JWT) for authorization. This endpoint produces the first admin-scoped API key for use in subsequent provisioning steps.
Integration with rsconnect-python
Because we have no admin-scoped API keys on a fresh Connect instance, Posit Connect authorizes the request from rsconnect-python
with a JWT. The JWT produced by rsconnect-python
is signed with a base64-encoded secret key and is scoped to request access to Posit Connect’s bootstrapping endpoint.
Posit Connect is configured with knowledge of the same base64-encoded secret key that was used by rsconnect-python
to sign the JWT. This allows Connect to verify that the token was signed using the expected secret key and not modified during transit.
If the JWT passes signature verification, contains the correct information, and has not expired, Connect will grant access to the bootstrapping endpoint, which creates an initial administrator account and provisions an affiliated API key. This API key is returned in the server response and is available client-side for use in subsequent provisioning requests.
Security Practices
The secret key used by the JWT signature/verification algorithm must be base64-encoded. rsconnect-python
requires that the base64-decoded key must be at least 32 bytes in length. Best practices also recommend that the secret key be generated using a cryptographically secure source of randomness, and that key length should be a function of the the signing algorithm.
For more details on best practices / standards regarding the keys used in HS256 signatures / verification, see:
RFC 7518 Section 3.2 for the HS256 minimum key length (256 bits/32 bytes).
RFC 4868 Section 2.1.2-2.6 for a description of the HMAC-SHA-256+ algorithms. RFC 4868 Section 2.1.3 specifically notes the importance of strong pseudo-randomness.
Custom Clients
The following section provides the implementation details needed for any custom client-side tooling meant to replace rsconnect-python
.
An example cURL
request which would replace rsconnect-python
might look like:
curl -H "Authorization: Connect-Bootstrap <YOUR.JWT.HERE>" \
-X POST http://connect:3939/__api__/v1/experimental/bootstrap
JWT Schema
Posit Connect Expects the JWT to be signed using the HS256 algorithm. Therefore, the expected JWT header is:
{
"alg": "HS256",
"typ": "JWT",
}
The expected JWT payload is:
{
"iss": "rsconnect-python",
"aud": "rsconnect",
"scope": "bootstrap",
"iat": <now>,
"exp": <some-future-time>
}
Additional information on the JWT standard is provided at jwt.io.
Request Schema
The bootstrap endpoint is located at POST /__api__/v1/experimental/bootstrap
. The endpoint expects the JWT to be provided in the Authorization
header under the Connect-Bootstrap
schema.