Skip to content

Rotating Keys

Daniel Molares edited this page Sep 5, 2025 · 1 revision

Usage

For a background, UDOIT must use sensitive API keys in order to access and modify data within your LMS. When setting up UDOIT for the first time, you may have generated an encode key that is used to encrypt these API keys.

However, if your encode key has been compromised, you may want to "rotate" your keys, meaning re-encrypting your keys with a new encode key. This can be done with the rotate-keys.php script under the scripts folder.

To use rotate-keys.php:

  • If you are using Docker, you can run make rotate-keys, which is an alias that will attempt to find the udoit3-db container's IP address (the database) and the environment file (.env).
  • If you are setting up UDOIT by yourself, you can run the script directly with PHP. From the UDOIT root directory, type php scripts/rotate-keys.php.

The following steps assume you don't use Docker, but there are only a few differences either way. (Using Docker and the make rotate-keys command will automatically fill in a few steps for you)

First, run the script with one of the methods above. You should then see:

Enter IP address of the UDOIT database:

Follow the instructions on the screen for each connection parameter needed for the database connection. Enter the information needed and then press the enter key to continue. For example:

Enter IP address of the UDOIT database: 127.0.0.1
Enter admin username of UDOIT database (default is "root"): root
Enter admin password of UDOIT database (default is "root"): root
Enter database name (default is "udoit3"): udoit3
Enter UDOIT database port (default is "3306"): 3306

Once you've pressed enter after entering the UDOIT database port, the script will print out the information you provided, and you can verify if all the information is correct. For example:

****************
IP Address: 127.0.0.1
Username:   root
Password:   root
Database:   udoit3
Port:       3306
****************

Is the database information correct? (Y/n):

If the information is correct, type y and then press enter. Otherwise, type n, and you can restart the process.

You should see the following message after pressing y and then enter:

Successfully connected to database!
Enter old encryption key:

Now, you need to retrieve your old encryption key, and paste it into the prompt. You can find this either in your .env with the DATABASE_ENCODE_KEY field, or in older versions of UDOIT, you may need to use a specific key that will be provided to you.

After pasting the key and pressing enter, you should see something similar to the following:

Enter old encryption key: BUwhAhjTUvqwxoc6e8DNoF5SucewGLnvnEf8eMXej5A=

Entered:
BUwhAhjTUvqwxoc6e8DNoF5SucewGLnvnEf8eMXej5A=

Are you sure this is correct? Make ABSOLUTELY sure it is, otherwise your keys may be lost forever! (Y/n)

If you know this is the correct key, type y and then press enter. Otherwise, type n and then press enter to re-enter the encryption key.

NOTE: Make sure to copy the entire key, but don't include quotation marks that you might see in the .env. For example, if your .env has the following lines:

###> database encode key ###
DATABASE_ENCODE_KEY="BUwhAhjTUvqwxoc6e8DNoF5SucewGLnvnEf8eMXej5A="
###> database encode key ###

Then the part that you want to copy is BUwhAhjTUvqwxoc6e8DNoF5SucewGLnvnEf8eMXej5A=. Do NOT include the quotation marks.

Back to the script, after entering y, the script will generate a new key for you to use, for example:

Are you sure this is correct? Make ABSOLUTELY sure it is, otherwise your keys may be lost forever! (Y/n) y

****************
CREATED NEW KEY:
xP9v5OMYJiUZ5nnS8ypfyOPVxpsn4vZr7gEo6CR4O+E=
****************

Would you like to automatically update the .env file? (Y/n):

You can automatically modify your .env to use this new key by pressing y and then hitting enter. The script will ask you to provide the location of your .env file. For most cases, you should be able to just type .env and the script should find the file, given that you ran the script from the UDOIT root directory. You will then see the following:

Would you like to automatically update the .env file? (Y/n): y
Please enter the path to your .env file (default is .env): .env

Found .env file: .env
Updated .env with new key.

Otherwise, if you do not want to automatically update the .env file (as in you typed n when the script asks you to automatically update the .env file), then you will receive the following message:

Would you like to automatically update the .env file? (Y/n): n
Please save this key into your .env file now!
If not, UDOIT will not be able to properly decode your keys when you run this script.
You can copy and paste the following 3 lines into your .env file if you do not have a DATABASE_ENCODE_KEY field,
or alternatively, update DATABASE_ENCODE_KEY to use the new encode key:

###> database encode key ###
DATABASE_ENCODE_KEY="xP9v5OMYJiUZ5nnS8ypfyOPVxpsn4vZr7gEo6CR4O+E="
###> database encode key ###

You will need to manually copy and replace the key in your .env with the newly generated key.

After updating your .env file, the script will prompt you to enter the newly generated key again just for verification. It is recommended that you also take another look at your .env file to verify that the key was changed, copy the key from the DATABASE_ENCODE_KEY field, and then paste it into the prompt, like so:

Please paste the new key to verify: xP9v5OMYJiUZ5nnS8ypfyOPVxpsn4vZr7gEo6CR4O+E=

Once you verified the key, the script will begin with the institutions table, which uses an encrypted field named api_client_secret. If you have multiple institutions, the script will print multiple database entries, but in this case we only have one institution:

****************
WORKING ON institution TABLE
****************

_______

Array
(
    [id] => 1
    [title] => MySchool
    [lms_domain] => myschool.edu
    [lms_id] => canvas
    [lms_account_id] => 1
    [created] => 2025-08-20 00:00:00
    [status] => 1
    [vanity_url] => myschool.edu
    [metadata] => {"lang":"en"}
    [api_client_id] => 10000000000001
    [api_client_secret] => xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOLD_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
)
* Old api_client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOLD_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

* Decrypted api_client_secret: xxxxxxxxxxxxxxxxxxDECRYPTED_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxx

* New api_client_secret: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNEW_API_CLIENT_SECRETyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=

* Sanity Check (Decryption using new database key): xxxxxxxxxxxxxxxxxxDECRYPTED_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxx
_______


Finished modifying institution. Commit changes? (Y/n)

You should see the Sanity Check field in the output, meaning that the script was able to correctly decrypt and re-encrypt the API keys from the database. If no errors are reported, then type y and then press enter. Otherwise, type n and press enter, which will not commit any changes to the database.

Next, the script will attempt to update the users table. The process is almost exactly the same as the institution table, however you may have a lot more database entries to look through, depending on how many users you have.

Similar to above, verify you see a Sanity Check for each user (you may need to scroll). Then, if everything looks good, type y and then press enter when the script prompts you to commit your changes.

You should see the message Committing changes to your database... and then the script will exit. Congratulations! You have successfully rotated your keys!

TLDR:

  1. Run the script (if using Docker, make rotate-keys, otherwise use php scripts/rotate-keys.php)
  2. Enter the IP address, admin username/password, database name, and database port of UDOIT
  3. Enter the old encryption key (either given to you or from your .env)
  4. Update your .env file with the new, generated key. Press y to automatically update, otherwise you will need to manually paste the key.
  5. Paste the new, generated key into the terminal.
  6. Verify that the script has correctly updated your keys for the institution table (an easy way to check is to see if for the database entry, the script outputs a Sanity Check with the decrypted key). Then, if everything looks good, commit the changes by pressing y and then enter.
  7. Do the same thing, but for the users table.

Potential Issues

An error occurred when trying to decrypt the key!

If you entered the wrong old encryption key at the start of the script, the script won't be able to decrypt anything in your database. You might see the following:

...
* Old api_client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOLD_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

An error occurred when trying to decrypt the key! The decryption key you entered might be incorrect. Ensure it is a base64-encoded string (usually 44 characters long).

Failed to decrypt! Either the key in the database may not be encrypted or the decryption key you entered is incorrect. Skipping...

Finished modifying institution. Commit changes? (Y/n)

In this case, DO NOT commit your changes for both the institution and users table (press n and then enter when prompted to commit your changes). You will need to re-run the script with the correct decryption key.

Failed to decrypt! The key in the database may not be encrypted, or the decryption key you entered is incorrect.

If you're sure you entered the correct encryption key, and you only received this message:

* Old api_client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOLD_API_CLIENT_SECRETxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

Failed to decrypt! The key in the database may not be encrypted, or the decryption key you entered is incorrect. Skipping...

Finished modifying institution. Commit changes? (Y/n)

(notice how the An error occurred when trying to decrypt the key! The decryption key you entered might be incorrect. Ensure it is a base64-encoded string (usually 44 characters long). message is missing)

Then you may have entries in your database where the key was not encrypted to begin with. If other entries in the database can successfully decrypt (as in, you can see the Sanity Check message) then it should be fine to commit your changes anyways.