Skip to content

yapily/jose-database-field-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JOSE database field encryption demo

Demo for JOSE database field encryption using Docker compose.

It is recommended the you read the three part series which will explain the purpose and background behind this initiative. From now on, it will be assumed that you are familiar with the articles and the focus for this repo will focus on walking through an example of how to run the various images created to implememt the database field encryption solution.

Setting up the tutorial

  • Clone this repo. git clone [email protected]:yapily/jose-database-field-demo.git; cd jose-database-field-demo

The repo contains all the components you need, especially the JOSE CLI which is in the directory ./jose-cli.

Setup the postman collection

The examples in this README will use curl, however, there is a Postman collection which is available in the /postman directory which you can use to quickly make requests.

Architecture of this demo

In this demo, you will spin up the following components as Docker images using docker-compose:

  • application-alice: This will play the role of your spring boot app which will access a PostgreSQL database with JOSE formatted fields.
  • db: This is a simple PostgreSQL database that you will provision with a sample table person. You can find the database schema at ./db/postgres/init.sql
  • jose-reencrypt-database: This image pack the JOSE batch tool and ensures that the database fields are continually encrypted with the latest keys.
  • jose-cli: This CLI will help you rotate your keys and propagate the changes to your application alice and db.
  • ./keys: This folder contains all the keys (valid, expired, rotated) you will use for the encryption. Initially, you will be provided a set with only 2 valid keys: one for signing and one for encrypting.

Application alice

This application manages Person Pojos connected to a database with APIs to create/retrieve them.

A Person is a simple object with the following attributes:

  • name: The name of the person that will be stored in plain text
  • email: The email of the person that will be encrypted in your database

This application is using the JOSE-Database open source, a Spring library contributed by Yapily illustrated in this tutorial.

The application offers some basic REST endpoints:

  • GET /persons/: Get all the Person objects. This enpoint decrypts the email on the fly and returns the decrypted value
  • POST /persons/random?nb-entries=3: Generate 3 random persons

In order to help you visualise the actual encryption happening behind the scene, we create an endpoint which returns a person as they are represented in the database, meaning with the email as a JWT:

  • GET /persons/raw: returns all the users as they are stored in the DB, in our case with the email as a JWS(JWE)

You can use the /persons/raw endpoint in order to see the current status of the database fields for example, how many fields are encrypted with a particular set of keys, but this can be quite cumbersome to use. Alternatively, you can also use the following endpoint which provides a summary of the JOSE database field status:

  • GET /actuator/jose-database

One JOSE-database that you may find useful is the custom actuator endpoints which provide information about the current keys that the application is using. This is quite handy to verify that your application has the right set of keys.

  • GET /database/status?details=true: This shows you the status of the table person with the details for each row.

db

This is a PostgreSQL database with one table person. See ./db/postgres/init.sql for more information.

jose-reencrypt-database

This is the JOSE spring batch tool that is configured to run against the PostgreSQL database on the table person for the field email. It's a job, meaning that once it finishes re-encrypting the field, it will shut down. In this tutorial, the job is executed each time we do a new docker-compose.

jose-cli

The JOSE CLI that is uploaded to this repo was the latest at the time of writing this README. You will need to have Java 11 installed on your machine as a prerequisite. You can verify that the CLI is ready for use by running the following:

 ./jose-cli/jose --version
"2020-07-10 14:23:56.540  INFO : Starting JoseCLIRunner on quentins-MacBook-Pro-2.local with PID 25757 (/Users/quentincastel/Development/GIT/github/yapily/jose-database-field-demo/jose-cli/jose-cli.jar started by quentincastel in /Users/quentincastel/Development/GIT/github/yapily/jose-database-field-demo)
"2020-07-10 14:23:56.543 DEBUG : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE
"2020-07-10 14:23:56.543  INFO : The following profiles are active: cli
"2020-07-10 14:23:57.470  INFO : Started JoseCLIRunner in 1.75 seconds (JVM running for 2.818)

./keys

A set of keys have already been generated to help you quickly run through this example and are stored in the ./keys directory. If you want to create a new set of keys, you can use the CLI: ./jose-cli/jose jwks-sets init -o ./keys

Demo

Step 1: Run the services and check the initial state

Run the services

To run the applications, run the following command with docker compose:

docker-compose up -d

This will spin up 3 Docker containers. You can verify that they are up and running docker ps:

❯ docker ps
CONTAINER ID        IMAGE                                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
237c05591ac0        jose-database-field-demo_alice-application   "sh -c 'java $JAVA_O…"   31 seconds ago      Up 19 seconds       0.0.0.0:8080->8080/tcp   alice-application
41fba9afaae8        postgres:9.6.9                               "docker-entrypoint.s…"   31 seconds ago      Up 30 seconds       0.0.0.0:5435->5432/tcp   postgres_jose_database_example
fd5505662230        yapily/jose-batch:latest                     "java -cp /app/resou…"   31 seconds ago      Up 30 seconds                                jose-reencrypt-database

Note that if the container jose-reencrypt-database has already completed, it may already be shutdown. In that case, don't be surprised if you don't see it:

❯ docker ps
CONTAINER ID        IMAGE                                        COMMAND                  CREATED             STATUS              PORTS                    NAMES
237c05591ac0        jose-database-field-demo_alice-application   "sh -c 'java $JAVA_O…"   5 minutes ago       Up 5 minutes        0.0.0.0:8080->8080/tcp   alice-application
41fba9afaae8        postgres:9.6.9                               "docker-entrypoint.s…"   5 minutes ago       Up 5 minutes        0.0.0.0:5435->5432/tcp   postgres_jose_database_example

Verify the initial state of the database

You can check that the service is up and running by calling the database status endpoint:

curl --location --request GET 'http://localhost:8080/database/status'
Status of the progress database at 2020-07-10 13:29:26
- Nb of rows: 0
-------------
Number of entries by key type:
- REVOKED : 0 ;
- EXPIRED : 0 ;
- VALID : 0 ;

The output shows that initially, there are no Person entities in the database. Next, generate 3 persons:

curl --location --request POST 'http://localhost:8080/persons/random?nb-entries=3'
[
  {
    "id": 1,
    "name": "dHAoGKOKuf",
    "email": "[email protected]"
  },
  {
    "id": 2,
    "name": "WZEmygOYHI",
    "email": "[email protected]"
  },
  {
    "id": 3,
    "name": "OvoMLKPHVK",
    "email": "[email protected]"
  }
]

Now, check the status of the database again:

curl --location --request GET 'http://localhost:8080/database/status'
Status of the progress database at 2020-07-10 13:34:41
- Nb of rows: 3
-------------
Number of entries by key type:
- REVOKED : 0 ;
- EXPIRED : 0 ;
- VALID : 3 ;
-------------
Number of JWTs using keys:
- 4ef01c58-8b45-4874-bdb0-864eb5ef7af6 : 3 ;
- ed24f836-5e22-4e0c-b9b2-dc4ee85128a9 : 3 ;

The output indicates that there are now 3 database rows (each with the email field encrypted with a set of valid keys). There are two keys, 4ef01c58-8b45-4874-bdb0-864eb5ef7af6 and ed24f836-5e22-4e0c-b9b2-dc4ee85128a9 which are used to encrypt the email as a JWS_JWE. This means that the email is first encrtpted as a JWE using the key ed24f836-5e22-4e0c-b9b2-dc4ee85128a9 and then signed as a JWS, using the signing key 4ef01c58-8b45-4874-bdb0-864eb5ef7af6.

You can now check that the GET /persons/ endpoint is able to read those Person entities and decrypt the email fields on the fly:

curl --location --request GET 'http://localhost:8080/persons/'
[
    {
        "id": 1,
        "name": "UAjKogHhAa",
        "email": "[email protected]"
    },
    {
        "id": 2,
        "name": "SkhstwfFQT",
        "email": "[email protected]"
    },
    {
        "id": 3,
        "name": "SMGwETaAQY",
        "email": "[email protected]"
    }
]

Success! Your application is successfully decrypting the email field on the fly!

To be convinced that they were encrypted in the first place, check the raw endpoint:

curl --location --request GET 'http://localhost:8080/persons/raw'
[
    {
        "id": 1,
        "name": "UAjKogHhAa",
        "email": "eyJraWQiOiI0ZWYwMWM1OC04YjQ1LTQ4NzQtYmRiMC04NjRlYjVlZjdhZjYiLCJhbGciOiJQUzUxMiJ9.ZXlKcmFXUWlPaUpsWkRJMFpqZ3pOaTAxWlRJeUxUUmxNR010WWpsaU1pMWtZelJsWlRnMU1USTRZVGtpTENKbGJtTWlPaUpCTWpVMlEwSkRMVWhUTlRFeUlpd2lZV3huSWpvaVVsTkJMVTlCUlZBdE1qVTJJbjAuSjJkVHJoYzlOWFF3SGJncTE4cjliRFNKbXNHUk9FTUJGa3RXWnh5TThXV0VCdUNRV29JaDRuNnZDMG5uU3dIUFh6VXB0OTZJNnpfeDcwZzlCYklDT040RFZ4QnRHM3JiQ1ZwV0UwV1dZNE1vZnZ5NU5ZRTlCS1ktYlZrc3JuZ2FkU2o3NFFSTEl5U1ZPQVBzTlpYS1VfVEFQM2xVcWktZ1V0Q1pMZFRrSHFzM1luM2NnV1VlUktNY0gyQWEyRzY4aE9QY19fd1lDTmpIMHZKZFR1dWcyWW03RUpkdm84U3dneHdiRjg3eERJOG52TjFfdFBBV19La2g4R0ZCd0N2XzJHNjlFaUpRSHlNdXhyaXlrUXpoR3BZWWRDVTdFNzN2M0NEUTIweXNoLXJmT0kyVzZjSTdubDlqc3Q2dVhIeDl5ZGhMbU5fNk5sZXZQbG9ZdzdHVHpRU1V2MmtpZ3lPbXFBLUh5VlBrbXo3Ri00ZGR0VFBBWGpiYWNLalRMS2tBTXhJeElXRm02bWc1YjJOdnZGZ040TXZxaTZiTGUxY09MaFhRczg5RGtXeTgyc05aRWFINEhxTVBhV0k1RWNqUTc5SElLbW5VR0lfNnR6Y2oyTF9OZTRNX19Sd3RRZ0Q0d0Z1WkZndTRWRWpNZ1Z5LVdXUnduOEZkeVJoX3RYUGtwRjZzNzFQXzVXNTdyNXpmQlJiMjNaNXhMbnNVbXpFbWZ1ekliUjZ4enRsRmRMbDJ3TFJfWmlueGREamRaeHllbzc3RWJSaUU0YTV5NFJzdGtoT21KdjhUTy1QZTlmM2FIeUJsazJZMXRWbmdnU1NPcXYwdWZNRjNkdzYxZU1nb2tTRkQ5QTd1R3BtdlN1aDFzY0oxa0ptZTU2ejd5OVBJSHFhZG5OZ2h1em8uYmdRR1Z1YUtqS3MzVDlyVDdUaERDdy5ENTB0Q1hPT0c1VzgyODBVcV9HWXpNamZyOUJEWk1fLW1QU1ZtWWVPWnFvLkY1RUtqWFZDaF9FYjBnblBsT3piZGdqbENrdm1oY3ZYQW5aeVAzY3VJVFk.lOoBDOuqJSTgYopneMW34FwLniXztV46VHq3v2eDxUYr7TPhHK6HglO8YNZECZsgSYcMifaeBgDniSNPj-QlxnkXwvPp3liJ9zOYSJaEvHq7hbKaZyxW2BwDERI90h-XYM3agGed9WSSAR_0_oMGDLZCxBiBfHahE0pRDHFS0nSj_yxiDyXsC23dy0oXo3rXRp8EvChK5xAV2_SaKiyPbJJZocrkYqoQXt21rZ-CSH46sVCT1Clj_IVvTiWSHw8n-nooSo6V8UtEnGRmFwJAZQgOqwPzL9dcn4ZAz9feb3HIDYmDHqOR5b4fjse2z1igat2sh5k2mFFXKKR7k_PFax2ALFId33zLtdguucRRw7aZcRB-hIpn0cgN9D7EYoPGIJt4O5PJGGx5b_srqgtOGA5HF7A2WLbocnzMp4myyPI402jsTLMVp-xiKgHw5EEILrmJ0GJ1xbp38aZKy-8v6_2bEmBdGwnfYELpv8hAKKf8EjCFlb1u_IrBxfcrcfYWCqS8eBHd9KEReh8EMy3qmcnIpOgjNyAI8XCpKMerUmGl4EKSXIxB7Oin65ArZ2tbnwufl_2MOlMk1odXzbmGKnxH9WYKh058zmNengGvq4xoWnA9uhT1iNpuRWWnRSQQHaY87GtVh04cUy5w9lfcb-2WLaHD_7FZxS5Rune0uNk"
    },
    {
        "id": 2,
        "name": "SkhstwfFQT",
        "email": "eyJraWQiOiI0ZWYwMWM1OC04YjQ1LTQ4NzQtYmRiMC04NjRlYjVlZjdhZjYiLCJhbGciOiJQUzUxMiJ9.ZXlKcmFXUWlPaUpsWkRJMFpqZ3pOaTAxWlRJeUxUUmxNR010WWpsaU1pMWtZelJsWlRnMU1USTRZVGtpTENKbGJtTWlPaUpCTWpVMlEwSkRMVWhUTlRFeUlpd2lZV3huSWpvaVVsTkJMVTlCUlZBdE1qVTJJbjAuSDVNSmNqRzk3Nm9KQ21HVEVNdXBJdHRCLXRORUdqaEphMFJyVmg3Q1RHU0hQdDljVFBaMkdFdmVsd1VacEtVcmYtQ2lfNjhtOGNsSVRBRC1VTXdwUkNtaTBHczAwSnpwN053dXJIQy1BLXVZM041LW40U1l5YjI2UG5xMjhRall0N1Z6Y3F3QjZNWHd5bjl6TjRvT3hkd3hwMzVhWlU4SjQ5OGRyUVdSVzFISDBtU0ZOSDF1N2tsZWFzRlp0cE80QjVvZlg2NTdHSUpxWDQtVk9Rd2N4UTZhWU1IRF9HUGIwNFFwdGtNdUFBMXdWRUVzbjJuZUg2ZExRNkFyYTJzSFZDQTdLVmZ4Z0d0VmRlNmdWWlk3UW5vRFBnUTdoN21HQ3plYjNGcHVCNmc2UldxYmNjdlNlYzhEMjRHSGJ2ZzlaVXRlczJNN3J6THFHOHB0VGNTVE4yUElISDJjdnFmN1UtQXA0VUhLX0Z4VFhaZmZMN01abDd5QzVXbFJkTXJoTjBMQ29sTmtObkJKYS1XUmxMYW5qd2VuTDR1dXBCLWUtejlGWEFIVVRaRGt1LTJncFRlaWx6Mnd2SmxzMXlXZTBRcUJzWFFIeVFiYU13YzMzeGdQcGIwQlpZU09EQmxZZ0hpcDE5d3NHQndabzdXWkZZSzVwTVNhZnpWTmZlbXRoWTdnOWQ2aW5JX2hzRkUwMC1pWVhEaUxtdTRBVWJMSDVfMHpzNXdkbzN3Ulp1M3E4LV9KMkk2ckZxY0o2VUttekFqblhPSWJFM25RTTZ6Sk4tNVRiQWdONWdDR25tbXlmM2tzSF9VM0xSamUyclFuWHYtOThKME5mVUthaVJRZHBNWW5RTUVfOUVpWEh4MXRQcjZldEZYZVhHa1VkMVJIa3poZGE0dEZWR1EuRnJSZnNSMXBmamVuWTBkcXU5MUt2US4zRVZjQzROSWpabmxrLXZjczctTW1FNkU0eHdYSXVfek5ZMmhjdlh5UHBNLm1WU3RkQnlBcVIwR0Q3b1JkQUNCUnVVVzdTcTVxM3VhcWZOdW96OWNoR0k.b0pVf0Rgn1s91FtO0QE2Hz45TiRRWTp4zhknUDuVCGaLFjQksiHgrlw4HBcopgzHkClrmY18FMhaaqxFP_O1asYFrhleYHezsoxw4i4RIx1RY0Pupi34nCWhe0KvtoCV004Dye7pSMPoSE0Svp3KclwPvpaUbVEcOWIfuANOf7astjCHfwUFpLTc19PiGTwD1_3-P_IHq3lvwCRnXEj0SXYeM-_Pt7A8gGeFjnQpBHWPE1F77U-GgcUQ1ZjrZYqK2eBbAlPRjk84pp6P0SD9A-S9hftKTaRfVNzkTu4VfDtDKneF-2T21N2LJU5GMVhdPGEhnPnQkX-2nHfcldP5dDBUeq3JuQQRYt235kY_eUUcgPS9A0G9Mi1ZnkTuVPa4PRx3K1j5n6okMPbTHRIxYgtgYMMrwkDWN0drX5dGodzaXBTnXs91QxJ7ogh36ewqA6R1IbVpVl5we1TMNhJwCYVqWyE10dpxMwavW533C0kcsxdZyriCj3nxBVDLns3XJLvH1D4gxibp_DHG_Gf2KQ9R9ruZusLzRwrBVIIzlTz-k1UqzQ5YUCfYqgIOcm6-l1EJVj7QGaDFiOAFfIYFdY32rVMyvfpKC5uyVbjdZ6DeHhKdY7r69evPKcbGwvCIW3stjKNfFm2WDQFK6nhTxFnCafpqLFhJX1Zh019c-3Q"
    },
    {
        "id": 3,
        "name": "SMGwETaAQY",
        "email": "eyJraWQiOiI0ZWYwMWM1OC04YjQ1LTQ4NzQtYmRiMC04NjRlYjVlZjdhZjYiLCJhbGciOiJQUzUxMiJ9.ZXlKcmFXUWlPaUpsWkRJMFpqZ3pOaTAxWlRJeUxUUmxNR010WWpsaU1pMWtZelJsWlRnMU1USTRZVGtpTENKbGJtTWlPaUpCTWpVMlEwSkRMVWhUTlRFeUlpd2lZV3huSWpvaVVsTkJMVTlCUlZBdE1qVTJJbjAuRVR1NlBhclJNYmJob3dfeENKUGp6d0VORmQwRDlzS19lZUx0WHdIX29OT284TnB6ZUdJS2hhUWVVOWoyREtjendFN1pLd0Y4RVJnMGNIUEd2S3hYeTJJLXREWmh4VVQzUjRoQWZPOUxTMDhsVTlNU3ljRmdGNnFwaEZMNnZ2TllDNWdxMmxnQ3dnNmVDY09rRjRjVDZGX3JzOEdyeTM0QnQ2alNhOHNFdlJvMFRTUGxjWDlPS01NUEdMYm5WR2hwQk9fQk5WaEtlYkNyblNpeXhvWmJ0ZWdQcVVYWnczZHdmcEczSjBiY0lVbkZBaU95U0FUcktRbDUwV0oyTkk1Z2dobTN5ZWVGd3NKcW9hbDNfc09TOWg5Z0pJeWlEQUcyMUNsR3N4MklTM0hSOFQ1a1ZySk9XWGtKcm9WbWJxRUJrM3NxWjZ6bVBGZWxoODJ0b3ozNW1pU2hvQUJ5Q1NlY3FvaG9CZnhOazd4OFZZR2RDNkpaa1MwMHYyaFZfcC1henZlYzJ4M0lLMHhRd0N3S3hTTEdfSEdUb3lGdUhhaURFVEZKZlFWcWlJM1hXMmkxbEJCOVpPbXRqOWw4RUg5bTJtS1ZLLWZ0MloweWtLRUQ3dFdrNngxUjN2OGlQMVNwMjNjazB1NG0xeDdUR3FLZ0dDSGZHRmJoWXZ3Wk43N1JsX0R5VmdkOW9aYnhCVTM4SDZhNFBUWGJjdG1USVF4WjE3RTRTZGd1emx3am1qakh1ZDJ1Smlkd0Z5ZnBVZmZKZ0s0VTZKaEtsdDNkY2hZaUZPRGFuN0ZsbDVwZi1MQ0FRMDdZT3lxSU9ObnlQbTF3QmpHckNiNUhoMWtrSERpWVNqVl95c3FrYkI2YVBqc3Utd2h4RTJHMGpqdUxtbV9waURXRzlXVUE4Zk0uR1dxSUZSTE5JeTJjQVNVWXA4S2lxZy40VlN0eGhQY0JwTXVBNEdjUnA0RmpJeUhnNkVWTTZZMHVsQ3ViRXdFWExNLk1YMjNSS0NxV3FtN0VuUExBWm84WlRINmVCTlZYcXp3dTJkNC11ZEQ1cmc.BBEIiqvr5FsYkA9nd1hv7LvGNGjPsxfAsP0wv3WYk2BMoSeSwpeChiw1s2BkZdgLoJo4q12bJWqmx_BYM5DAA96eEbguou6wDnCrbkqGvZI3Vy8gQsqpFfK-hN_V1tR5k8ptC5JeATx901B8l9StVdiYdoDRguuuxz1Pj_R4RqiifAW_R6-KXn5he9SCrzIjuOQUUffiERev8RnbhmsvDdtY4usSbEY64bspM-II-RcTV_Z0bOz78Ai-YZQAvYV-lI6HNcznrll0hGcwFfLfSc_gXDmE4L4eCze_uPs5bcaB7zGsLPBV_Rx-aLFISRoh2OypDXMiwlT2TVG2d4tVsvtmZEk2UpNVDKYaqK3C6KnAXq6Iinzt7OjRT0KHg6D4NwFZyt3u9F-xqyPXnyDCyBB7RxJyT3V5qg1seoun9mWXaqE7I1gJcygbf6lIHSl-KJ0MhDFyIsvnkebqz_EmfXv2x-J4n0BGGMzliO9KAAEjOsUSHK2UR2_KHt0oQUY6xQonqu1GS3clnLUbxUb4bG5pp-04y0iasrd89A_8WRgNyTCsQqhsUls3x2NE6hN1R7wqZ-Hp3vnc0KIXknt_w-6P1shTu1Ypz6E8BJnnrtAGzl0NhzrbGNfzW17nm02-Qk5FJ7Jd5fup495dIppUuMjBCpD_iqPeuRGgqeeRU1M"
    }
]
Check the actuator endpoint

Check the JOSE database actuator endpoint:

curl --location --request GET 'http://localhost:8080/actuator/jose-database'
{
  "validKeys": {
    "keys": [
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "sig",
        "kid": "4ef01c58-8b45-4874-bdb0-864eb5ef7af6",
        "n": "mpWKCJHMEKF2sijLHINvvTbKbmk_APGtOYQRZiAaf_detrNStT6NR_4eaEkkCZrfDteOZZ6OvKWLp_hIkDyz3PV6bq1CdRhQL0yT_RVjJ-jRyMZYwgcldULJORnBZ6HIOFGnPoPT-FyAuE0IDW-ttoGrpAF_IAsS1hMGCTI5xo97HbfMlKu93w8FfWY3-ke8JsjRF7jc5nNYmjzrM90OGiKBXfM84aajY3SEzWhuxzXTSTTT4PqkgaBI7vDu9O-qifDhxE9ZNIPBpVbj3YNw9443LuA1Ylp5xaGQdWyFOZV0CFtGX4FphlZsA5te3gPd0Dhn9vR1SVLk06T6GD5eUII5LfYP0ROcbCH4bpq8mvgJZFcsBhH6ua9k0EvEymSgpEH5AeHCnizWk-2rh_rk441i1wEPxikdqQQWj-f6xgmcFowmF-IGg6OGZ7iECZYZHtUdM9MzuVMZ49VKjJ7mbGd9WSEdSKzEr4UhMACGy9pbj4Nk6GAwMwb3N1WhpX7D6bTub5uspoKx-BaDde8IViOahLsIiKzCIATtMHAhR4l17R_UKEQ7ebpxwfGhDrrLK2Ih1fYpr4mk4MWwYoqvA7FEtaqBHigOwNwAutLCxcn8C6dvBbyPjg8agfKz3Ex5jzZfl1OvxC41DBY4SEGArGOZpnaFMrs7OcfSeEAMYz0"
      },
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "enc",
        "kid": "ed24f836-5e22-4e0c-b9b2-dc4ee85128a9",
        "n": "oxeuO_A0pBC-yUCOAVYN10H9HOz34-jksG_MG4rPRSwi7esUG1NbZ9V7D286gfGAh_Z4rp2mh0FqObscpstMoOsy3vEwas4CAkbhLk8OEmiWrLnR_VuTEI8Dog0X8GoyhXFLzWa61UqFQuotizEyA03aXT4qC0CJRm4I3YuIzReZU20npVWNuTyAtuHtsgLafYzsC5L92kV_-Dmjhe17yYb-X_FppyWCxIlgxz3uPo-N4cxBxChr2jyKxhPPkGTEEI23YEpRdMINEyNijVrwSWOr44AfosTDVRQiApPqyNYzoznMaSl-HznYVdLnipWi07uaNp4w3EeRJuLxHwfdG3D6T22oGrHLv5Sgy3H-9UdyS0OLoElQfuN0Z1x_qX9wSAyKYyEDfTm5VfvosRJj-lQVJloZuAX03r3VbsKbdILT6eBQvBhOjZf_-JSRJb8kSlDYKX7Eyg_KfIbLiNK03259xUiMjcWqwGcsvtMQM9sKob7_LDWNalcYDFiLYmfVqmrHs7ZEWFdx9lr_AspRo27X8sMRgNYiaslhjfVgbB61XbHhRFo7czeYbLFlZSnMh6h60wunfGpqeWjLub4HEJG2BQhhQF6Oo2eTv_ULrZDawRTIUuK_u333KmgBJZd87vJLaSyjnds7Wx5oxFHX3r4hwL7RFbedMcZO86_OZQ0"
      }
    ]
  },
  "expiredKeys": {
    "keys": []
  },
  "revokedKeys": {
    "keys": []
  },
  "currentEncryptionKey": {
    "kty": "RSA",
    "e": "AQAB",
    "use": "enc",
    "kid": "ed24f836-5e22-4e0c-b9b2-dc4ee85128a9",
    "n": "oxeuO_A0pBC-yUCOAVYN10H9HOz34-jksG_MG4rPRSwi7esUG1NbZ9V7D286gfGAh_Z4rp2mh0FqObscpstMoOsy3vEwas4CAkbhLk8OEmiWrLnR_VuTEI8Dog0X8GoyhXFLzWa61UqFQuotizEyA03aXT4qC0CJRm4I3YuIzReZU20npVWNuTyAtuHtsgLafYzsC5L92kV_-Dmjhe17yYb-X_FppyWCxIlgxz3uPo-N4cxBxChr2jyKxhPPkGTEEI23YEpRdMINEyNijVrwSWOr44AfosTDVRQiApPqyNYzoznMaSl-HznYVdLnipWi07uaNp4w3EeRJuLxHwfdG3D6T22oGrHLv5Sgy3H-9UdyS0OLoElQfuN0Z1x_qX9wSAyKYyEDfTm5VfvosRJj-lQVJloZuAX03r3VbsKbdILT6eBQvBhOjZf_-JSRJb8kSlDYKX7Eyg_KfIbLiNK03259xUiMjcWqwGcsvtMQM9sKob7_LDWNalcYDFiLYmfVqmrHs7ZEWFdx9lr_AspRo27X8sMRgNYiaslhjfVgbB61XbHhRFo7czeYbLFlZSnMh6h60wunfGpqeWjLub4HEJG2BQhhQF6Oo2eTv_ULrZDawRTIUuK_u333KmgBJZd87vJLaSyjnds7Wx5oxFHX3r4hwL7RFbedMcZO86_OZQ0"
  },
  "currentSigningKey": {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "4ef01c58-8b45-4874-bdb0-864eb5ef7af6",
    "n": "mpWKCJHMEKF2sijLHINvvTbKbmk_APGtOYQRZiAaf_detrNStT6NR_4eaEkkCZrfDteOZZ6OvKWLp_hIkDyz3PV6bq1CdRhQL0yT_RVjJ-jRyMZYwgcldULJORnBZ6HIOFGnPoPT-FyAuE0IDW-ttoGrpAF_IAsS1hMGCTI5xo97HbfMlKu93w8FfWY3-ke8JsjRF7jc5nNYmjzrM90OGiKBXfM84aajY3SEzWhuxzXTSTTT4PqkgaBI7vDu9O-qifDhxE9ZNIPBpVbj3YNw9443LuA1Ylp5xaGQdWyFOZV0CFtGX4FphlZsA5te3gPd0Dhn9vR1SVLk06T6GD5eUII5LfYP0ROcbCH4bpq8mvgJZFcsBhH6ua9k0EvEymSgpEH5AeHCnizWk-2rh_rk441i1wEPxikdqQQWj-f6xgmcFowmF-IGg6OGZ7iECZYZHtUdM9MzuVMZ49VKjJ7mbGd9WSEdSKzEr4UhMACGy9pbj4Nk6GAwMwb3N1WhpX7D6bTub5uspoKx-BaDde8IViOahLsIiKzCIATtMHAhR4l17R_UKEQ7ebpxwfGhDrrLK2Ih1fYpr4mk4MWwYoqvA7FEtaqBHigOwNwAutLCxcn8C6dvBbyPjg8agfKz3Ex5jzZfl1OvxC41DBY4SEGArGOZpnaFMrs7OcfSeEAMYz0"
  },
  "encryptionMethod": "A256CBC-HS512"
}

This output shows that your JWK sets have been loaded by the application properly with only 2 valid keys and no revoked or expired keys. The system is in cruise mode which means it is able to start serving the APIs while continuing to encrypt/decrypt emails.

Step 2: Key rotation

Now you will see how to rotate keys and make sure they are propagated properly to your applications and to the old fields in the database.

Generate a new set of keys by rotating the current keys

This is done by using the CLI:

./jose-cli/jose jwks-sets rotate -k ./keys -o ./keys
   "2020-07-10 14:48:29.163  INFO : Starting JoseCLIRunner on quentins-MacBook-Pro-2.local with PID 26267 (/Users/quentincastel/Development/GIT/github/yapily/jose-database-field-demo/jose-cli/jose-cli.jar started by quentincastel in /Users/quentincastel/Development/GIT/github/yapily/jose-database-field-demo)
   "2020-07-10 14:48:29.168 DEBUG : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE
   "2020-07-10 14:48:29.168  INFO : The following profiles are active: cli
   "2020-07-10 14:48:30.093  INFO : Started JoseCLIRunner in 1.554 seconds (JVM running for 2.469)
   "2020-07-10 14:48:30.246  INFO : Rotate the keys
   "2020-07-10 14:48:30.247  INFO : Move all the valid keys as expired.
   "2020-07-10 14:48:30.247  INFO : Create new keys
   "2020-07-10 14:48:30.247  INFO : Create a new RSA key for 'sig'
   "2020-07-10 14:48:33.020  INFO : Create a new RSA key for 'enc'
   "2020-07-10 14:48:34.006  INFO : Save rotated JWK sets into './keys'
   "2020-07-10 14:48:34.030  INFO : Key rotation completed.

The -k flag specifies the directory to your current set of keys and -o specififes the directory to where you want to generate the new ones. In this example, you are overriding the current keys with the new set of keys.

cat ./keys/valid-keys.json
{
  "keys": [
    {
      "p": "4N4Tloon5aukQ-maDJgTwwIoEZyXXMDLwfGf9_QJs4j3_yFUucMkU777wAjfdXFW5xPgiYcfgxcNn6UiaNHavSPNZmYoWgYAtlRn_dmga_Edp6-EAK-DHdCNWjdpo03kDdYp6kD2HcFFDysI0qvepmwwa-TlzrZ4z8dMYC9Hhu7MGO0VmqzPmwz1u31oNK6S-GcaVw0slDr605Z8_gmdqO3fXIBDqhCX1UFxXIz5UX4O1OOKGvis4QxlfPGPkDrZu41YkLf0HSrG6Kf3oF8r0_b2opGtuDefFyoQBAGe2RIIBTHHA9qpFyJRyr2jkHF2IleAR_92mRtiTGh8T1yIVQ",
      "kty": "RSA",
      "q": "pJjan6F3bi0LK__-qZLR9SrzLGauAKiHCgVKh7ekyosdslNeKCYLXocXp2Nhnv7TGD1Cdp5pyB9QomqLFlWewFlTVv5kFyeUXhTDmdlgFN6zgr4MoYFV2in0p9Kn0z3uvenK7AlX-EF01h2KjwSnXrRnRVmE-JDTxsIF0iRm9_JtAKn2lkgSD9kL7mhiADBVzBPzncprvh4S-jkU6cdC8ocLAhr95upjSBsitt3HXPYrGeCSAuh9JzJspbv5V05n3etiArJ6gmZiOXheFM0tbkGiqJhVkqhLvcu5uzo4bMPZTZjAvwR5tmuLWr6t6WkMMfAJvl7t0o_82_Hri8Pd8w",
      "d": "SvOllFw_XucKKlGM9Fd-O0zkLY3YT4W_GBdYxL03tCsAUqWuUK6sxJXH2aJDeJSCNFIydsb04l9ExolKiOhxAp1UUVQg0ZZuw2oKLAGd2A_qSCJl99nb9Smz3fhQ3TyIxuKG8AB9jB0YQXjk-Zfy2R4N1jbDiE-_bcLc_zKQjrEO1TWpyC3K6Y5aY-0QjCkd93fCD6QCGQtb_R52UWew6SxqAUGtCzkxiWSC_2QzGkJoOnHD1cEOmYdk7DPChlZi_rceEsZiHy_B6RB0jGUUJO9jbTaeFNV8uFW4j7CnMq-Lqrpk5qLDab9nfhOrTTQJyr-fYj9OKONg_gyvGknruHE_pY9CuSat-ciTJQ2W-fnvcF7sNIyY1ts44DkZnDUCPMbOfdmdgFKmWQsxtdhk8mmcK697hD4lQIaO5tUf_jYYdUeAd6UeOGpI-oLJ-isgSP-Fy5Uo0OJrdwOhe25V6o-iFuAW0KWlyNntmx3LnI-P_m-uFf_QwhYHZO9agrvLkQDYLzs3O2P04yMrYCP5gOoUAY18GFax89Gix7WkIJZblIYcx43N3XTXb4SnjQuoYtXMsnZ1PiM2-PGlJV_jxDGlP2a_ow56ycWQc8rsOIunt6rORvctI5OnoEMAsZozJsk9wnPDlV62F32geUAcgmVM5XC10d7DCofwIr-ir1k",
      "e": "AQAB",
      "use": "sig",
      "kid": "8e9bb522-bde6-4491-ae0b-3e92427c0ad2",
      "qi": "WGAJTFXn9pa7u0jH7Q4l32RnqoC1QWXamideo8khARhvZfWeXX7bJ5ChjypqtttIZqkFe-wp7fUSubp1H30nA_D9TKc-2mU--J9GrUbp3xWqit8bEq-GAlH-mknh8J9_aRuXrnjRt-m5e10Wqupq-4Ga3bo9XHuxXZY4S6fsso694l_XAH3aPBlCXWiJAo2Stp2vRGyBs3Wd2p24n2E-i-XgaqT1xslmpa_DvDEQ0d4TE6uJWGQyYJXli_NFt0Xfh7TDdqjfn1s0i31rTKudb4wkoK28Qxxyh8t4-5rOfdw3JuYFpMAiF9B4izxnl_k7JlBlf7GsDioAbuZkxloimg",
      "dp": "CZVNTmga5S3YdVB6UTkV9oScAowi40AQLvbGM4IB-9XFg-j-vF_1p2AHSJrYMyAebQCq3BGXJTYRTZFzEvaGlPL2qPuHkraYxyx3thjVPmRrOB9Bx-my881UiNi9tsj2BCTxaltUYdY_xDK4UIoklgEcWyzJInMiWPCMb7j0GmsI5bMM7aeZvWji_BePHlemSdHTDIyyLqsIz4WlVApC3tUsZLvOpmvInL0KQMB9S5zMswPzeczJSVoG5TlCPgpUBysx8BD25VtSWM33vqzvqDvpLOp6ddRhAlK3lgQfqe6byuThL2fdNvAufi5wzxIWz8Xc4LShcEr7eHgnfBZcdQ",
      "dq": "MdNvwwj-_WQ3UI-DCNRAKKZizJscq2hY0Ki_Ygwun32zdKsWArNZl7jvaSWFhLsBLgJFX2EfBoysPS5hglZS40lnGBuUMwoxOLWybJ1IH6k20Co16qIbWhp_TFpRoXnLDsR6QC-n6Kfv9W0l55tyCxIzfOPXg-NbqHxNhMquPPqvEpdg5SdWCGQc34PLvuDi6A9WHPsM2JWECylCcm52jrJgm7eOCtwDR-2m-ZJzamm-rGu155l3YWk7SIR5u3spqB08IzLiMR1LOLh-Sm--A_VshvruVKILo53LUKkUMaCr5HiMSIbTTWyK1-KHBPRe07MlT_KuraIW2oIGWt3lDw",
      "n": "kJSIcWZUhUvgontICnY-J33aNUHY0EBeQtLCU7pwzwVFR_8aYfJfZuiymqXxay8-FjN0Xp6bsntHzJEhmY_o0Lxdol_BWi4hsfWCGzrPJgMTrJQAlvBZNNrpxubJa8SUWADEaPj_I1YTFTB9pDdXC1Ty3lxoIEY5SsWDCnKa0pV9Z_5dZu6I4AIzJjxbyPJ17SkZgFQK-pQKGbZwhqZQWBvQFx1lZ5Wz3wrgOXC_zFJUn7nSUcqFAup9uaTNaylS_aCZL0ziyKPJuXIJ4I-17nhdtY4UzrIQCHUhSuJL3zqC9aPQiZ2nd9l9nHyy4ucPLH1OqAjdOkeFV3xjXPtCtzJDqUf6RYOQ9L9vkp0i_WqL9W1SUO_k0TIugTSCGyay71sN-OAc2HFZoG6nkdUsUWESgDpZHlcTfIZHRBkVnJqOXuU0nrBKMGTbYEKYeoZkHQa0Bm1X-hQ6zo5nduPCqXp1yy9pTUSl0QDP516D6WhIr57z8HCxSuf4YtEZZkC3-5SGMUgCbSfxbiE1vPCrUQxPj1ub1X8R65mF0_XI1O6F9WvHpFqcgIqaQTUF_jak3E_yxpifJ6twLvpvMsHyAf4W0etJ5Q0QVHgvR3_mttOnuglzjWGlZiW4pCzIufnhnKr6DvjrjAnOnunDaNyBwjtRf5fyKiJznYJbCzZFya8"
    },
    {
      "p": "7hQYLHKUl6R5ycZBD-w_akzTy2lAewVUSYKDi9rMNXEg1414JjHqGJ5GB5yItb99WToou8y41--VoT47QYxNPEliyc9cdD9Bx7TYDxkoWoy5kPLjp-xrx_ZLzeaus6gDufE21CfCLBRbs83gTKTBFItkDiSIm_VFjqSJkCzH9rqtgYD3EAQK5laGm4_A6TmCn2J061-vWmtboPsv0l9Ln7mmjVmSYQ_netUQLCQnKsJNrO92-4t9sL3WaQRgJRogXLAPRgn3cagA7gSIj2nXFzTzavimf43nzYrmq62eKHP0IF9sw4YghybMDmyPotelKxYiBRs-tS-NbdLz1yxUPw",
      "kty": "RSA",
      "q": "jHC6m_KYUY0XgedhUu8pCmVV1H4ci0EQiLyj-XkWG8k_IbWG5yAxshBRHlpTh4zFikmbCVKrrhy8am6crJHIVeKLHUwRAdQjXeAmoT1TQ8XMpV9G-8N4O_FRRsDt61OOTug4qTLceYPYAAbASqre2ZkIe5Csu8328uZPEUiphr0nelktaFiQ52j6YHOKBftqQbrw5bi1CL9r97FJfBV6UuzHvy6XaX6WDst9YIoG8Fe64hmUvKX9jefR8DBjI0jJDW-oVVP9DJqfpFDcc3yjWCnpvDrVD8exM_AEO9jsri6u0CgTY3xy-KiXwmDKq2cakZvcXi1-n61pQmiwapGhCw",
      "d": "JzNJ3d5KJajczmorVHIlR8gkoSc8h0PHbmZ-IMhdA5yqpVr6MYry6TF8QiUSl4J502B9p6lT_cOyxEPTRNq0cvJTiZ2VBb6yJs5cJF2THbGozOhfizokqMB85C6puPGs_94Vn7AmPPsfRw6qK12VY4ljACjikrnWpf0Pihv6MnbaHHsY_LArD-c3BcQ-89VHGRHvj3WZLdKMAoWyyvDm2PJmASgoJ5UiJt5CFhJp-_WmmjeYIGEPcee7CNAc-fVzGP_R9hJzABlWA3oxr_dxTSoObzJIddsWSHZVKyCG8ZkIqLAgnfPo83CEu7YsWWbqeu-QrnL7C7_y9nuAjkAbUtAcGzZjm9WPGWIn0YhOpmO3tGke58rRRo-GbbzIC_Ffd4vlOI8DKyP8GsZI5PgVSP3zhU9CkKBZA3iI6j1ucNvQ1iTXWEJuLfvGS07mHE1693FY8OSCGWacHfH5vozz0mp8xBV-sWLOTTn8pimbxt3KkSp8KhqYiePfd1jzZKScbstIJCZpKuSaSAWiTX9wxC9XzrELMqDtVvOH7eHcIva2XapS0sf6mOwCH4i1PYL3DQUtPuYkqjfS1kKAAGc-JjjXGmUuMDN6grqjw75wwczATcrSWPoo3oFjw9W95Os74NJFjJf_s9FAU7m-P_aNEb96DqPOMZjkUSCtiw6rmkk",
      "e": "AQAB",
      "use": "enc",
      "kid": "494ea5dc-f8c7-4439-971f-5349a898d05c",
      "qi": "dI54zVIXso-XufohettXjOI5Jlbrhga2sbeoPO7bea6dZmoeiVqy-wgYI2tKkw0s9ZjSfSrEyqQ8ko7zSduJMLd9-JxgBPsyCwZ7uAF2yNc-z3_iuD5-c2gWY7gXwdifu58tE_QTAgFuWzT7aG8QKV0t53abSxT9zSBlPt2HglT5Zu99x_NSuXcn3V4dYSEmd40HsAP4Yi3F7w9UZ8Eu6gIQ8oYGoE9XMXgsuCTy6aDk9XBM6AN2GW2Y_3wqQhYvuyLGeeHG3FXQvszkBUzkcV_K6s2qiQP44Ic6MRg5q6mbfouaOAdLwsBodscpMD1csG4N2RiSXl8X6HrBKeqjKQ",
      "dp": "VBrlL06LD8ca_xz6fxWGkZbyezmDffI0BIQG1LFG0tpUL9HaUCPx_yBqvOWfphUvwwW4vh9kbWRGB-BkLpPR9So3q_OFRcvTASnx6eOJTfPI2lvz8K6kpM9tmB-WOAFyz41XQTuKbOgEPVDNnEXXr9pOTnC5kd7j47BcqIIpYhAwmz9kCFRlRVnr06jFDZ8zdfriMwRqfhbPF9-k1Ty1CogbPnQWMhPcQphiTjW3YHOj3SP7dIGitX1a8V6KWJESPaw0uRlsQMqJCYywcXmCcsBR_cg5iXYoHYSkWKHM7Z2I8KbFVY1ckGI0VCQl2fE0eDQpcIRfcsKJw_JyEeGnIQ",
      "dq": "IO_HNA-_HVEjtDmZn6OrUl7VtFInS5lk0Uy8gCOfxcB65-L00nvAa-xbueyhLmcbZQVCMPuMe_cNUUDDyc0e2NWanrJaQr2H1dpd9O62-mwHRLmFokIDjrtXvmo84jXkaCkaMMRW5MDBBbCPpHNSdGHplWEmwZzaT7knzfvmlk0CVzVW6uPqh_sczUYLlr-R-fxnxth8zKJoJd0USN-Yop4ZcoLwy7L-alXa_6sfWXqZv7EUKvIa9w7pM5WFip7lWBtZtTlPXYdd7WFxcjxG6sRZpuV9VogUzQN7WrXTPD6CjRr5ARoMtLiFbvbYUT6LAp81HXk5-yTmTMbUqQmiZQ",
      "n": "gpvTjoNy-LmR_W-PHj1Lvq88YRaW5kLGUiyRwXUhSpiqkk6NFip8bDxa8TTgHxfVmJbGtgl4X-N6hTNZoNyklHTM9JZuxdIH1BGiYaIG3L15nfz8iGqdhB1UoW3X23-zLli6V5YVxn4XFypdrjZOrPndMVMLKV3ABGvVglLHGvREqDfg3a6g6kuGCeG2BnVTtyGCFmaDLlrd46ZscnlExJdFDOmoYaCZNabwhEnSAsEevTX9WDq4YSGdxZQoN2wdPKkgRnDuC_paYozjAVebEMfZY3fPK6VDVRkxFacO4_dIkQvplvOsfSs8utNO48ztubHoFD8dbD5ZkrVPEwlCzzVRgquksLahZwpBek1pQHQL402-7OlyvW-iQ9tM3ZKHQH7oNhuA1V72T8El1XVeZEz3ghuXSHMeuJHjYqVSaEUez1cG-5RNPO4_Nz2KTBVR1V834UFO-1IkokmsOdJ5T4iDal2BBlDWpanOvyCC_LGXH1J27W7pRZHUFUJApnXNq2KM9SfepJKZK6ieXXbMOtbOm17ZtXiJcoRvKrHWQ65rCVbsjB1z0mbQNPtk1PUhyj9CJ8wgToGie6xZAfOxkOAHV_pvLbOhRe0G17MtsrRS8w7-2THO9K9cUqbJZQhCBAgQlUhOPdKV9J5bUFIcZNlnPRCmwBQnGIopGu2SPbU"
    }
  ]
}
cat ./keys/expired-keys.json
{
  "keys": [
    {
      "p": "yFn8N-jGb2QNi4QmkrSbwwpuoIDQrs6D3BRffy-aS6Tl0r2HZTw3J_NeeNMA1dK3CTwI5zW_XzXngVyBJnEjGaAHlYIDAJdpTkSCH5Av2m1hd7s4IxzB-oS1g4redvNPaMPcRIR8Ba5LoEb24yAFxOdWZP8UghjxlNHCjDPcXemwCPRTbHL76a1WkZmL_ufG4lKHsRY2JGiI4UimnZzxJWxZ-4EfBaJ3qB8XQIMwNHOdLuY_fIovC7Gr3qFqxSgM5Dt0xb1p8Rd8lVJ3se1jTkwYipKeG_T-R0ModVap43ht2kpuW7gpMiOB7-TN-p02RzgWHwVj8vmjgB8SoJTBmw",
      "kty": "RSA",
      "q": "xYVCsLo19zpz5-vUZujjX28uuHIlukjdg_BsgB_DhheIkX0etKR42xZadOMNHe9IcnMqGjXvFw8TaSeWrlLl8VlUppaNw8e6DjCgO9pQu9QKleVVB3u7cdJXrgi4xPYNT3rfjAiFL2MTOMryGL7Sj6UTObYtCgYNqq-5stRYgO_lC6ZUERSzaRS0u91tjOXwRdUzLr6RTsfXBtg7bXyjB4K3VBCE3lB_gvOOb9RhFdz1s_DJojFj_0gptT5HSFZR3lRSml3cpEnAoTUaXKwK7vlWK1mnNGqGfx-gX1eUQlIw8mXylTUKAN1YMpEA1mrUSiKe4olYHde2sG1MLs7IBw",
      "d": "d48xM2-QZUx8gU8LyQHfanj2GG9OS2ygjduXmWU7Gb45gxUu4v9-RjBFVGM9fDBMVS5i9DWuMDnZyhA-D1DjzAIQr4lR3T7wxaR00Um5ZySrHJ5MB8V_MzJ0b7V74KtAME73C2Lqjyz8YY8yqzG1KXMhTbfamu31o50TDgnKpchTcKi3kkVClUMI-_QTV4AkBdtL3Q0dzR9pZ-G2CGbwgUYuyHtYmy5HMKTuEfCzvV_kCrrRJTC2C4vs3OF77_Vt8UJdW3gDhpphK4AIvUrsFIvqIldG8ssHY9OR50AHyoHNPKlbxIJTG5O79w40UYKsDF-UCW0JSazTTt5KkHWse2SCKmI3ykYCHYDgCI6VgPGsQjxd5b66F5NMsAZyy4bQ-tiGYnY2R_4Mc1WEhtz-H2eRiUYvpCSvcfhVUImLzKElOvSvgdFtowlUUlGvbkZyjdO8lSnS5oGUMG5vE1t8XqUryICHFr998Oci6cqwG6lijexR7rYWl_WtGQZhproIg2t9YUnvTT_GUV0uSwZ0UIIqRfVEEi50jCG54uhBDHiD1X898ySE8HXzGedk76APMeNB9yyn_WH66K2euuIYvXfieGsSWakYirlw_Ba74vryQnCIsEr83DFh58tQjQFeTJNw8J9x3LBtrjTaNRLIOmBiTl4oQZ-MQ2K81PBNqAE",
      "e": "AQAB",
      "use": "sig",
      "kid": "4ef01c58-8b45-4874-bdb0-864eb5ef7af6",
      "qi": "uYWwUt0X6u3WPLOCq2ABg7wfs5gJnJt2Ng36La77FX123mxH3nAPeRUa1EIJuBvuHKS_j9QdnJtSmgXkeDihEu7UkOyfE_RFGXYB2-8Za0Tn2idfURHAyVXHcn2FNsFH4yDhIR750zLTcYrNnOfv_YRkLTHaKbowIWj_Ggo77QI9pv6jDUIhh6U-fGSwx4oTFoRmE3zVBBsZkRPY4L66IW5ecbzGS7OMSwkGiGtJgeoGBw4Icst0aL7Pdsv0Z9oeki4WlgV_ZYUInwVLKxRqVPQUuHJw_Hx3ksZcYdWS6MijMWULSQr6uu4pUASZb58nuKUIFmxVdEc_w6V4HmpY6A",
      "dp": "ESpciLHB5qNM4co1v9YHjmNjbQ78Ui3RcFayg-QhNR_wrOieJBdPpnWcf3-cj7VZB0qEfMLHHbIxnoy9Z_zDhBuI6s9T0IYoeJM4Dto8r1s1wZthyOha2krqflW0j75y7EfzpE8xjQ8M3bOWzYjd1av4Y_jS2f6nHBgIshhzZfxyn6HHUABeAvxd8WWVcAaNrLBjfdGoW-A08hBWbiSXKJyq7Ph4HvR3igj35ggXZjcNnYoOoG36b-cOEaoEytWOnTNW4uZCoGxhuS1yoeTz4C5239CGCWEpNBPV8I-3SIz15IECCYuyw9_07wfMeg9kKh_tDUVZ9eRblMuUvftgxw",
      "dq": "bBuZ-tyQePZ3RfLf2EuTV0KlUbK4T5NeGr7Ww_GetJ_g0bCnw7tZoqBDdkJnhYDYKDw8SQhICljoCN_wKw2YaVa5bExu3z9L6ERZDylYktVlzdEtjuD8ITo9XzXK25LIij34aM6pBty1Qpphk4Wt_Y0eTrIVSK0zgb6YZvauUjP7KzsoPAkWgWch3Mk_EqUvsykT0HvhUDs0x7xGGpDjMlMrQEmiT4PDpsrjpPWbBbpgiNI7qhhaYPkASwEBRuhn-sYwR-kjwI_VbOaBvUM04MN7lFKHn7rGToHi5wwqS3ps6988vMnA5eRAR7zxtmnWM5VrXRZLMlpE1Z-c2Om4tQ",
      "n": "mpWKCJHMEKF2sijLHINvvTbKbmk_APGtOYQRZiAaf_detrNStT6NR_4eaEkkCZrfDteOZZ6OvKWLp_hIkDyz3PV6bq1CdRhQL0yT_RVjJ-jRyMZYwgcldULJORnBZ6HIOFGnPoPT-FyAuE0IDW-ttoGrpAF_IAsS1hMGCTI5xo97HbfMlKu93w8FfWY3-ke8JsjRF7jc5nNYmjzrM90OGiKBXfM84aajY3SEzWhuxzXTSTTT4PqkgaBI7vDu9O-qifDhxE9ZNIPBpVbj3YNw9443LuA1Ylp5xaGQdWyFOZV0CFtGX4FphlZsA5te3gPd0Dhn9vR1SVLk06T6GD5eUII5LfYP0ROcbCH4bpq8mvgJZFcsBhH6ua9k0EvEymSgpEH5AeHCnizWk-2rh_rk441i1wEPxikdqQQWj-f6xgmcFowmF-IGg6OGZ7iECZYZHtUdM9MzuVMZ49VKjJ7mbGd9WSEdSKzEr4UhMACGy9pbj4Nk6GAwMwb3N1WhpX7D6bTub5uspoKx-BaDde8IViOahLsIiKzCIATtMHAhR4l17R_UKEQ7ebpxwfGhDrrLK2Ih1fYpr4mk4MWwYoqvA7FEtaqBHigOwNwAutLCxcn8C6dvBbyPjg8agfKz3Ex5jzZfl1OvxC41DBY4SEGArGOZpnaFMrs7OcfSeEAMYz0"
    },
    {
      "p": "2m6rh140AtbRLk7InkZrb74-NoAjZgpZ4WHsmjk2I-wTpFCl16nvaxhzT-JMKiQ1rwLUHO771D_I4memf24z47cdxNMwqaoyZznkqut1H9CBachFmB3ric6UckoKrVWrjjecMn95qwvMhqcRdQhxcUCy-J_SyJHIsfy8DLVCuDasisnZf2P9fxtQxDoadhoXMlryIaJyuo6dK_pK4qq2ZWDnlFJrKkn9evqa0zFU7yawZCKegysZIrJrOh6NjVvu6K-vbqxhZRjsJMABgwhMK12ozAMPCZHAGGAp6Y2SxawZ-axyDXwLgB2ahrCsGvdfeJfNXxYIM6gMCLE7MnFHeQ",
      "kty": "RSA",
      "q": "vyR2A0pzFE63VXoXRCyh7dbhf3BCKcC8qmOx-iP0ufD25DJpmUq5HEjYJB20ybFnwhywnx6J5gw1dpNQMSXAnJ1OK1p4tMEaRmFyV7ij6IQ49E-PQiNJN0_EEZbS9scJxgJY-YDvSBbpUJgHI-oyuYFpn_OSwOG0ggf5DAGt6i8sqUa3WaaaAWOHySkvCjf6l4qyuwEKYf3F52TR7Khn-TSUClEtKL17thdtoJJVctoRyL3J7LSGuXkIeyaYN9cs6g24dhO_KtlckxMLTBXMHq1IHDVNnOXnhRkmgND7SVpnBRkfCV8Otqmxs7wn6CK4Yv9Pdj59F6QlKTG96EQhNQ",
      "d": "JuavGHzjEX8tArPzKz5rbry-sveS6TnT0oHYHXmulsFAU5-O3DW1x76T68qMGhKQpd2US5Iu9nQT8lE_NEmprXhsWeENu2wH7qMZcwJISPvJdMmd3ODK41g5dZ3J5_5sroennQaz6cwsnRleY6UIWOFpBHSfcq-iDrqQQsfViZXnbI7MthMCCvzzdqvNFni3xNqoMtqM0lNhgsO8zWUn8ZnRcvESUlwQJPDftKaA_UsgfItL5I3_q75lG3n-OGLQoWIsKzuO0lq246m9CBp41giAJ3OYGCr2rIRw2EyP4_ezuWs_5pWPD8OsZkw4DkZC4F4PGpgA74nihXP8L3qgslk-syNB60EoBFpwJi_HHzoZFxpfvFIkEA9aEWorUCkaBcJIPR3xa6pedaSVS-z96An6rOIV5qlFTsC_m4QxZccywcdVllHgcst11VQJRs8UEzHDzmyvNh3d0XkgoFQs114MbsdgZigRavOJq-yQwIU7xwazDmBejsGfC2CeO8TsNurmI9rAu86JjsJMMpYD76l4YjxkYV8S-iPf0T1STwlUkYglXbMaIrkLtT0-Jl8hq6kf2-3sbh8_yQxZPVJMvEQQ6OpmtD-D692gCRsy4DhTuUPn0sPuLU-OtUBaV-qk1PURJ8mKWlwPkr2uilM90QKYLyCyJYCwkYLVfp-xpgE",
      "e": "AQAB",
      "use": "enc",
      "kid": "ed24f836-5e22-4e0c-b9b2-dc4ee85128a9",
      "qi": "cg1hbE1o23AyOUyeJwZWE6WwJJTpFdK9onK9NYHbQLkwXO9fX-rhQl7FEegc81LpRrGW41Vc3f8aNoZfjBTD-xWsIyGoutyzCwj6TuQima3iRqjj6VwDM4oPElYUlQX6jNb4RDpJOYmBZHq7jj6gYwaMQm2RPRh_-01FynIbvPayBOYgnfLjudrtwcNU4-Q-6IGXj-V0lSoAzCCZBHWg6YyrzCEtiZGa5pQPVwK3JeYx_hTEDU1m3Eq15sSqSwmdQIVbHxKl6YGqX-BbFEC8RNz9oWJA1Cadsf4QdE4tvn00dLXdZiogn5Q705e2qnu48Uww78OO2EBYt3c_Ygypsg",
      "dp": "HMlrB6sNlbYz2TN-0wUa0Z4z2sDmaWNB1yctpGGX1gId0JDkWljF-co-IDAFs6QUAx2PUMTaIW3KjrP0SGUAp6kRXkgq6KFKhTom_bOMOwYimAtRyKtgyEeWXr2NTKy2sEZ56lnMchNa___ymAbl1HQfYg7GG7LCzVouekpFIbvq31ucs2I9HUw_R60Uoa3skrFTqcUb86Qp6IrS5a5z3UZ5Hp4CC4-2vUdbsiuVMvNZWckKNOUwKddztDQkmZWdFcNZjm9fYpB3RpybVmZ4i1qLjV910uAHfe7mdyY2SqDUx4fHfCl15ouAOvH7rI4fYeg3o6lmqVAjTd31nD87mQ",
      "dq": "FrkP6n48RgrBksDL6UfhDDRCZHME-o-2Hg9yBgmmO0ChKSmxEg8nCGzEfS6m4l9btWDRwmjP_fAvnuQOYXlad4Pf2hmMRfi61ekZvcHugmLNnoWiwzsMpi2uYmTquXmZ-NcomqiwSYKnw_P-zU83LoRq-R_sr09ltRubiMjeUvu-tHT6sQa0QjwB1XE27WEQQlmzu7V49YNEtqhuqFKw4ZhVjRBvbOtxvIj2eGNNEzVHbfTZ_3DKn1v7HSDOcbz70utEpYzdagujDLzz19yzgmYZL3lKu789Eb6WrDOr2-GKY7nDzcpmJmLwBCz3FYqjHum5GZZ-KoRSAp6uM-F9jQ",
      "n": "oxeuO_A0pBC-yUCOAVYN10H9HOz34-jksG_MG4rPRSwi7esUG1NbZ9V7D286gfGAh_Z4rp2mh0FqObscpstMoOsy3vEwas4CAkbhLk8OEmiWrLnR_VuTEI8Dog0X8GoyhXFLzWa61UqFQuotizEyA03aXT4qC0CJRm4I3YuIzReZU20npVWNuTyAtuHtsgLafYzsC5L92kV_-Dmjhe17yYb-X_FppyWCxIlgxz3uPo-N4cxBxChr2jyKxhPPkGTEEI23YEpRdMINEyNijVrwSWOr44AfosTDVRQiApPqyNYzoznMaSl-HznYVdLnipWi07uaNp4w3EeRJuLxHwfdG3D6T22oGrHLv5Sgy3H-9UdyS0OLoElQfuN0Z1x_qX9wSAyKYyEDfTm5VfvosRJj-lQVJloZuAX03r3VbsKbdILT6eBQvBhOjZf_-JSRJb8kSlDYKX7Eyg_KfIbLiNK03259xUiMjcWqwGcsvtMQM9sKob7_LDWNalcYDFiLYmfVqmrHs7ZEWFdx9lr_AspRo27X8sMRgNYiaslhjfVgbB61XbHhRFo7czeYbLFlZSnMh6h60wunfGpqeWjLub4HEJG2BQhhQF6Oo2eTv_ULrZDawRTIUuK_u333KmgBJZd87vJLaSyjnds7Wx5oxFHX3r4hwL7RFbedMcZO86_OZQ0"
    }
  ]
}
cat ./keys/revoked-keys.json
{
  "keys": []
}

Now that you have rotated your keys, the next step is to propagate them to the application.

Use the rotated keys

In order to see the necessity for the batch tool to re-encrypt database, you will first observe the database in its bad state. To make things easier, first shutdown the demo application:

docker-compose down

Next, only start up db and alice-application:

docker-compose up -d db alice-application

Now, check the actuator endpoints to verify that the alice application is using the new keys and not the old ones:

curl --location --request GET 'http://localhost:8080/actuator/jose-database'
{
  "validKeys": {
    "keys": [
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "sig",
        "kid": "8e9bb522-bde6-4491-ae0b-3e92427c0ad2",
        "n": "kJSIcWZUhUvgontICnY-J33aNUHY0EBeQtLCU7pwzwVFR_8aYfJfZuiymqXxay8-FjN0Xp6bsntHzJEhmY_o0Lxdol_BWi4hsfWCGzrPJgMTrJQAlvBZNNrpxubJa8SUWADEaPj_I1YTFTB9pDdXC1Ty3lxoIEY5SsWDCnKa0pV9Z_5dZu6I4AIzJjxbyPJ17SkZgFQK-pQKGbZwhqZQWBvQFx1lZ5Wz3wrgOXC_zFJUn7nSUcqFAup9uaTNaylS_aCZL0ziyKPJuXIJ4I-17nhdtY4UzrIQCHUhSuJL3zqC9aPQiZ2nd9l9nHyy4ucPLH1OqAjdOkeFV3xjXPtCtzJDqUf6RYOQ9L9vkp0i_WqL9W1SUO_k0TIugTSCGyay71sN-OAc2HFZoG6nkdUsUWESgDpZHlcTfIZHRBkVnJqOXuU0nrBKMGTbYEKYeoZkHQa0Bm1X-hQ6zo5nduPCqXp1yy9pTUSl0QDP516D6WhIr57z8HCxSuf4YtEZZkC3-5SGMUgCbSfxbiE1vPCrUQxPj1ub1X8R65mF0_XI1O6F9WvHpFqcgIqaQTUF_jak3E_yxpifJ6twLvpvMsHyAf4W0etJ5Q0QVHgvR3_mttOnuglzjWGlZiW4pCzIufnhnKr6DvjrjAnOnunDaNyBwjtRf5fyKiJznYJbCzZFya8"
      },
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "enc",
        "kid": "494ea5dc-f8c7-4439-971f-5349a898d05c",
        "n": "gpvTjoNy-LmR_W-PHj1Lvq88YRaW5kLGUiyRwXUhSpiqkk6NFip8bDxa8TTgHxfVmJbGtgl4X-N6hTNZoNyklHTM9JZuxdIH1BGiYaIG3L15nfz8iGqdhB1UoW3X23-zLli6V5YVxn4XFypdrjZOrPndMVMLKV3ABGvVglLHGvREqDfg3a6g6kuGCeG2BnVTtyGCFmaDLlrd46ZscnlExJdFDOmoYaCZNabwhEnSAsEevTX9WDq4YSGdxZQoN2wdPKkgRnDuC_paYozjAVebEMfZY3fPK6VDVRkxFacO4_dIkQvplvOsfSs8utNO48ztubHoFD8dbD5ZkrVPEwlCzzVRgquksLahZwpBek1pQHQL402-7OlyvW-iQ9tM3ZKHQH7oNhuA1V72T8El1XVeZEz3ghuXSHMeuJHjYqVSaEUez1cG-5RNPO4_Nz2KTBVR1V834UFO-1IkokmsOdJ5T4iDal2BBlDWpanOvyCC_LGXH1J27W7pRZHUFUJApnXNq2KM9SfepJKZK6ieXXbMOtbOm17ZtXiJcoRvKrHWQ65rCVbsjB1z0mbQNPtk1PUhyj9CJ8wgToGie6xZAfOxkOAHV_pvLbOhRe0G17MtsrRS8w7-2THO9K9cUqbJZQhCBAgQlUhOPdKV9J5bUFIcZNlnPRCmwBQnGIopGu2SPbU"
      }
    ]
  },
  "expiredKeys": {
    "keys": [
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "sig",
        "kid": "4ef01c58-8b45-4874-bdb0-864eb5ef7af6",
        "n": "mpWKCJHMEKF2sijLHINvvTbKbmk_APGtOYQRZiAaf_detrNStT6NR_4eaEkkCZrfDteOZZ6OvKWLp_hIkDyz3PV6bq1CdRhQL0yT_RVjJ-jRyMZYwgcldULJORnBZ6HIOFGnPoPT-FyAuE0IDW-ttoGrpAF_IAsS1hMGCTI5xo97HbfMlKu93w8FfWY3-ke8JsjRF7jc5nNYmjzrM90OGiKBXfM84aajY3SEzWhuxzXTSTTT4PqkgaBI7vDu9O-qifDhxE9ZNIPBpVbj3YNw9443LuA1Ylp5xaGQdWyFOZV0CFtGX4FphlZsA5te3gPd0Dhn9vR1SVLk06T6GD5eUII5LfYP0ROcbCH4bpq8mvgJZFcsBhH6ua9k0EvEymSgpEH5AeHCnizWk-2rh_rk441i1wEPxikdqQQWj-f6xgmcFowmF-IGg6OGZ7iECZYZHtUdM9MzuVMZ49VKjJ7mbGd9WSEdSKzEr4UhMACGy9pbj4Nk6GAwMwb3N1WhpX7D6bTub5uspoKx-BaDde8IViOahLsIiKzCIATtMHAhR4l17R_UKEQ7ebpxwfGhDrrLK2Ih1fYpr4mk4MWwYoqvA7FEtaqBHigOwNwAutLCxcn8C6dvBbyPjg8agfKz3Ex5jzZfl1OvxC41DBY4SEGArGOZpnaFMrs7OcfSeEAMYz0"
      },
      {
        "kty": "RSA",
        "e": "AQAB",
        "use": "enc",
        "kid": "ed24f836-5e22-4e0c-b9b2-dc4ee85128a9",
        "n": "oxeuO_A0pBC-yUCOAVYN10H9HOz34-jksG_MG4rPRSwi7esUG1NbZ9V7D286gfGAh_Z4rp2mh0FqObscpstMoOsy3vEwas4CAkbhLk8OEmiWrLnR_VuTEI8Dog0X8GoyhXFLzWa61UqFQuotizEyA03aXT4qC0CJRm4I3YuIzReZU20npVWNuTyAtuHtsgLafYzsC5L92kV_-Dmjhe17yYb-X_FppyWCxIlgxz3uPo-N4cxBxChr2jyKxhPPkGTEEI23YEpRdMINEyNijVrwSWOr44AfosTDVRQiApPqyNYzoznMaSl-HznYVdLnipWi07uaNp4w3EeRJuLxHwfdG3D6T22oGrHLv5Sgy3H-9UdyS0OLoElQfuN0Z1x_qX9wSAyKYyEDfTm5VfvosRJj-lQVJloZuAX03r3VbsKbdILT6eBQvBhOjZf_-JSRJb8kSlDYKX7Eyg_KfIbLiNK03259xUiMjcWqwGcsvtMQM9sKob7_LDWNalcYDFiLYmfVqmrHs7ZEWFdx9lr_AspRo27X8sMRgNYiaslhjfVgbB61XbHhRFo7czeYbLFlZSnMh6h60wunfGpqeWjLub4HEJG2BQhhQF6Oo2eTv_ULrZDawRTIUuK_u333KmgBJZd87vJLaSyjnds7Wx5oxFHX3r4hwL7RFbedMcZO86_OZQ0"
      }
    ]
  },
  "revokedKeys": {
    "keys": []
  },
  "currentEncryptionKey": {
    "kty": "RSA",
    "e": "AQAB",
    "use": "enc",
    "kid": "494ea5dc-f8c7-4439-971f-5349a898d05c",
    "n": "gpvTjoNy-LmR_W-PHj1Lvq88YRaW5kLGUiyRwXUhSpiqkk6NFip8bDxa8TTgHxfVmJbGtgl4X-N6hTNZoNyklHTM9JZuxdIH1BGiYaIG3L15nfz8iGqdhB1UoW3X23-zLli6V5YVxn4XFypdrjZOrPndMVMLKV3ABGvVglLHGvREqDfg3a6g6kuGCeG2BnVTtyGCFmaDLlrd46ZscnlExJdFDOmoYaCZNabwhEnSAsEevTX9WDq4YSGdxZQoN2wdPKkgRnDuC_paYozjAVebEMfZY3fPK6VDVRkxFacO4_dIkQvplvOsfSs8utNO48ztubHoFD8dbD5ZkrVPEwlCzzVRgquksLahZwpBek1pQHQL402-7OlyvW-iQ9tM3ZKHQH7oNhuA1V72T8El1XVeZEz3ghuXSHMeuJHjYqVSaEUez1cG-5RNPO4_Nz2KTBVR1V834UFO-1IkokmsOdJ5T4iDal2BBlDWpanOvyCC_LGXH1J27W7pRZHUFUJApnXNq2KM9SfepJKZK6ieXXbMOtbOm17ZtXiJcoRvKrHWQ65rCVbsjB1z0mbQNPtk1PUhyj9CJ8wgToGie6xZAfOxkOAHV_pvLbOhRe0G17MtsrRS8w7-2THO9K9cUqbJZQhCBAgQlUhOPdKV9J5bUFIcZNlnPRCmwBQnGIopGu2SPbU"
  },
  "currentSigningKey": {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "8e9bb522-bde6-4491-ae0b-3e92427c0ad2",
    "n": "kJSIcWZUhUvgontICnY-J33aNUHY0EBeQtLCU7pwzwVFR_8aYfJfZuiymqXxay8-FjN0Xp6bsntHzJEhmY_o0Lxdol_BWi4hsfWCGzrPJgMTrJQAlvBZNNrpxubJa8SUWADEaPj_I1YTFTB9pDdXC1Ty3lxoIEY5SsWDCnKa0pV9Z_5dZu6I4AIzJjxbyPJ17SkZgFQK-pQKGbZwhqZQWBvQFx1lZ5Wz3wrgOXC_zFJUn7nSUcqFAup9uaTNaylS_aCZL0ziyKPJuXIJ4I-17nhdtY4UzrIQCHUhSuJL3zqC9aPQiZ2nd9l9nHyy4ucPLH1OqAjdOkeFV3xjXPtCtzJDqUf6RYOQ9L9vkp0i_WqL9W1SUO_k0TIugTSCGyay71sN-OAc2HFZoG6nkdUsUWESgDpZHlcTfIZHRBkVnJqOXuU0nrBKMGTbYEKYeoZkHQa0Bm1X-hQ6zo5nduPCqXp1yy9pTUSl0QDP516D6WhIr57z8HCxSuf4YtEZZkC3-5SGMUgCbSfxbiE1vPCrUQxPj1ub1X8R65mF0_XI1O6F9WvHpFqcgIqaQTUF_jak3E_yxpifJ6twLvpvMsHyAf4W0etJ5Q0QVHgvR3_mttOnuglzjWGlZiW4pCzIufnhnKr6DvjrjAnOnunDaNyBwjtRf5fyKiJznYJbCzZFya8"
  },
  "encryptionMethod": "A256CBC-HS512"
}

You can see that the application has successfully loaded the new keys.

Next, check that database status endpoint:

curl --location --request GET 'http://localhost:8080/database/status'
Status of the progress database at 2020-07-10 14:00:48
- Nb of rows: 3
-------------
Number of entries by key type:
- REVOKED : 0 ;
- VALID : 0 ;
- EXPIRED : 3 ;
-------------
Number of JWTs using keys:
- 4ef01c58-8b45-4874-bdb0-864eb5ef7af6 : 3 ;
- ed24f836-5e22-4e0c-b9b2-dc4ee85128a9 : 3 ;

This output is exactly the same as before except the previously VALID keys are now EXPIRED. No rows have been updated and tne fields are using the old keys. Note that the Ids of the JWTs match the kid of the expired keys.

You can verify that you are still able to decrypt the fields by using the /persons endpoint:

curl --location --request GET 'http://localhost:8080/persons/'
[
    {
        "id": 1,
        "name": "UAjKogHhAa",
        "email": "[email protected]"
    },
    {
        "id": 2,
        "name": "SkhstwfFQT",
        "email": "[email protected]"
    },
    {
        "id": 3,
        "name": "SMGwETaAQY",
        "email": "[email protected]"
    }
]

Success!! This is an important feature required for the application to allow the smooth rotation of keys without any downtime.

Next, see what happens when you create new Person objects:

curl --location --request POST 'http://localhost:8080/persons/random?nb-entries=3'
[
    {
        "id": 4,
        "name": "wDuFqLEOcf",
        "email": "[email protected]"
    },
    {
        "id": 5,
        "name": "jhjqQvQAeu",
        "email": "[email protected]"
    },
    {
        "id": 6,
        "name": "srFMplbMRX",
        "email": "[email protected]"
    }
]

Check the status of the database again:

curl --location --request GET 'http://localhost:8080/database/status'
Status of the progress database at 2020-07-10 14:04:40
- Nb of rows: 6
-------------
Number of entries by key type:
- REVOKED : 0 ;
- VALID : 3 ;
- EXPIRED : 3 ;
-------------
Number of JWTs using keys:
- 494ea5dc-f8c7-4439-971f-5349a898d05c : 3 ;
- 8e9bb522-bde6-4491-ae0b-3e92427c0ad2 : 3 ;
- 4ef01c58-8b45-4874-bdb0-864eb5ef7af6 : 3 ;
- ed24f836-5e22-4e0c-b9b2-dc4ee85128a9 : 3 ;

You can see that the new entries are encrypted using the valid keys. Your application is therefore able to read fields encrypted with expired keys but new entries will always be encrypted using the latest keys. Note that the first two ids are the valid kid values for the valid keys and the last two are the kid values for the expired keys. This is good news as it proves that once you migrate fields encrypted with expired keys to the latest keys, the application will no longer contain any rows encrypted with the old keys.

Step 3: Migrate the old fields by re-encrypting them with the new valid keys.

In step 2, you didn't run the jose-reencrypt-database docker container in order to see the importance of migration.

You can now run the re-encryption batch job to migrate the database:

docker-compose up jose-reencrypt-database

Note that the alice application is still up and running and potentially serving requests.

Once you see !!! JOB FINISHED!! in the logs, the batch job has successfully completed. After running the batch job, once again check the status of the database:

curl --location --request GET 'http://localhost:8080/database/status'
Status of the progress database at 2020-07-10 14:09:47
- Nb of rows: 6
-------------
Number of entries by key type:
- REVOKED : 0 ;
- VALID : 6 ;
- EXPIRED : 0 ;
-------------
Number of JWTs using keys:
- 494ea5dc-f8c7-4439-971f-5349a898d05c : 6 ;
- 8e9bb522-bde6-4491-ae0b-3e92427c0ad2 : 6 ;

Success!!! Now the database has all the emails fields encrypted using the latest valid keys. Note that once again, the id of the JWTs being used are the kid values for the valid keys.

Conclusion

This completes the demo for encrypting database fields using Docker. In the third part of my article series, you will see how you can achieve the same thing on a Kubernetes cluster.

About

Demo of the JOSE database field encryption

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published