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:

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.