keenauth_directory_token
The keenauth_directory_token resource creates a SCIM bearer token of a directory for the identity provider that provisions users and groups to it. The provider keeps the token in state only encrypted to an RSA public key that you give it.
resource "keenauth_directory_token" "okta" {
directory_id = keenauth_directory.acme_okta.id
label = "Okta"
expires_in_days = 180
public_key = file("${path.module}/scim-token-key.pub.pem")
lifecycle {
create_before_destroy = true
}
}
output "okta_scim_token_encrypted" {
value = keenauth_directory_token.okta.encrypted_token
}
The token is never stored in plain text
The API returns a SCIM token once, in the response that creates it, and no endpoint can read it afterwards. The provider encrypts the token with your public key (RSA-OAEP with SHA-256, MGF1 SHA-256 and an empty label) and writes only the base64 ciphertext to encrypted_token. The plain token never reaches state, a plan file, an output or a log. Only the holder of the private key can decrypt it, so a leaked state file does not leak the token.
Create the key pair once, outside OpenTofu, and keep the private key out of your configuration:
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out scim-token-key.pem
openssl pkey -in scim-token-key.pem -pubout -out scim-token-key.pub.pem
After tofu apply, decrypt the token and give it to the identity provider:
tofu output -raw okta_scim_token_encrypted | base64 -d | \
openssl pkeyutl -decrypt -inkey scim-token-key.pem \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
public_key must be a PEM-encoded RSA public key (PUBLIC KEY or RSA PUBLIC KEY) of at least 2048 bits. A private key or a smaller key is rejected at plan time. If the provider cannot deliver a token, it revokes the token at once and the apply fails, so no valid token exists that nobody holds.
Create and revoke only
A token cannot be changed. Every argument (directory_id, label, expires_in_days, public_key) creates a new token when you change it, and the old token is revoked. Destroying the resource revokes the token.
A token that was revoked outside the provider, or that expired, is removed from state on the next refresh, and the next apply creates a new one. Deleting the directory deletes its tokens.
Rotation
A directory has at most 2 valid tokens; a third one is rejected with 409. That is enough to rotate without downtime: with create_before_destroy = true the new token is created before the old one is revoked. Give the new token to the identity provider in the same change window.
Arguments
labelis 1 to 100 characters, without control characters and without leading or trailing whitespace. The API default isToken.expires_in_daysis 30 to 730. The API default is 365.encrypted_token,created_at,expires_atandidare read-only.
Import
The resource cannot be imported: the value of an existing token can never be read again, so an imported token could not be delivered. Revoke an old token with keenauth directories tokens delete <directory_id> <token_id> and let the provider create a new one.