Add the setup of Azure Key Vault as a secrets store and how to retrieve a secret in the application. Update git-ignore to do not commit dapr components with secrets

This commit is contained in:
Pierre Malarme 2022-12-01 13:58:13 +01:00
Родитель fcc24f91c8
Коммит 45a996824f
10 изменённых файлов: 317 добавлений и 13 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -11,3 +11,4 @@ _site
.jekyll-cache
.jekyll-metadata
vendor
dapr/components

Просмотреть файл

@ -1,5 +1,6 @@
package dapr.fines;
import dapr.fines.fines.DaprFineCalculator;
import dapr.fines.fines.DefaultFineCalculator;
import dapr.fines.fines.FineCalculator;
import dapr.fines.vehicle.DefaultVehicleRegistrationClient;
@ -26,6 +27,11 @@ public class FineCollectionConfiguration {
return new DefaultFineCalculator(fineCalculatorLicenseKey);
}
// @Bean
// public FineCalculator fineCalculator(final DaprClient daprClient) {
// return new DaprFineCalculator(daprClient);
// }
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();

Просмотреть файл

@ -0,0 +1,28 @@
package dapr.fines.fines;
import java.util.Map;
import finefines.FineFines;
import io.dapr.client.DaprClient;
public class DaprFineCalculator implements FineCalculator {
private final String fineCalculatorLicenseKey;
private final FineFines fineFines;
public DaprFineCalculator(final DaprClient daprClient) {
if (daprClient == null) {
throw new IllegalArgumentException("daprClient");
}
final Map<String, String> licenseKeySecret = daprClient.getSecret("secretsstore", "license-key").block();
if (licenseKeySecret == null || licenseKeySecret.isEmpty()) {
throw new RuntimeException("'license-key' is not part of the secrets store.");
}
this.fineCalculatorLicenseKey = licenseKeySecret.get("license-key");
this.fineFines = new FineFines();
}
@Override
public int calculateFine(final int excessSpeed) {
return fineFines.calculateFine(this.fineCalculatorLicenseKey, excessSpeed);
}
}

Просмотреть файл

@ -4,16 +4,16 @@ import finefines.FineFines;
public class DefaultFineCalculator implements FineCalculator {
private final String fineCalculatorLicenseKey;
private final FineFines fineFines;
public DefaultFineCalculator(final String fineCalculatorLicenseKey) {
if (fineCalculatorLicenseKey == null) {
throw new IllegalArgumentException("fineCalculatorLicenseKey");
}
this.fineCalculatorLicenseKey = fineCalculatorLicenseKey;
this.fineFines = new FineFines();
}
private final FineFines fineFines = new FineFines();
@Override
public int calculateFine(final int excessSpeed) {
return fineFines.calculateFine(this.fineCalculatorLicenseKey, excessSpeed);

Просмотреть файл

@ -0,0 +1,16 @@
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: secretstore
spec:
type: secretstores.azure.keyvault
version: v1
metadata:
- name: vaultName
value: "kv-dapr-java-workshop"
- name: azureTenantId
value: "[your_tenant_id]"
- name: azureClientId
value: "[your_client_id]"
- name: azureClientSecret
value : "[your_client_secret]"

Просмотреть файл

@ -27,7 +27,7 @@ To complete this assignment, you must reach the following goals:
## Instructions
1. Open the file `dapr/kafka-pubsub.yaml` in Eclipse.
1. Open the file `dapr/kafka-pubsub.yaml` in your code editor.
1. Inspect this file. As you can see, it specifies the type of the message broker to use (`pubsub.kafka`) and specifies information on how to connect to the Kafka server you started in step 1 (running on localhost on port `9092`) in the `metadata` section.
@ -65,7 +65,7 @@ spec:
In the `scopes` section, you specify that only the TrafficControlService and FineCollectionService should use the pub/sub building block.
1. **Copy or Move** this file `dapr/kafka-pubsub.yaml` to `dapr/components/` folder. (when starting Dapr applications from command line, we specify a folder `dapr/components/` where Dapr component definitions are located)
1. **Copy or Move** this file `dapr/kafka-pubsub.yaml` to `dapr/components/` folder (when starting Dapr applications from command line, we specify a folder `dapr/components/` where Dapr component definitions are located).
* from the root folder, run the following command:
```bash
@ -75,7 +75,7 @@ cp dapr/kafka-pubsub.yaml dapr/components/
## Step 1: Publish messages in the TrafficControlService
1. Open the file, **TrafficControlService/src/main/java/dapr/traffic/fines/DaprFineCollectionClient.java** in Eclipse, and inspect it
1. Open the file, **TrafficControlService/src/main/java/dapr/traffic/fines/DaprFineCollectionClient.java** in your code editor, and inspect it
2. It implements the `FineCollectionClient` interface.
@ -97,7 +97,7 @@ public class DaprFineCollectionClient implements FineCollectionClient{
}
```
3. Open the file `TrafficControlService/src/main/java/dapr/traffic/TrafficControlConfiguration.java` in Eclipse
3. Open the file `TrafficControlService/src/main/java/dapr/traffic/TrafficControlConfiguration.java` in your code editor
The default JSON serialization is not suitable for todays goal, so you need to customize the Jackson `ObjectMapper` that it uses. You do so by adding a static inner class to configure the JSON serialization:
@ -149,7 +149,7 @@ The default JSON serialization is not suitable for todays goal, so you need to c
Dapr will call your service on a `POST` endpoint `/collectfine` to retrieve the subscriptions for that service. You will implement this endpoint and return the subscription for the `test` topic.
1. Open the file `FineCollectionService/src/main/java/dapr/fines/violation/ViolationController.java` in Eclipse.
1. Open the file `FineCollectionService/src/main/java/dapr/fines/violation/ViolationController.java` in your code editor.
2. Uncomment the code line below
@ -169,7 +169,7 @@ Dapr will call your service on a `POST` endpoint `/collectfine` to retrieve the
// }
```
4. Open the file `FineCollectionService/src/main/java/dapr/fines/violation/KafkaViolationConsumer.java` in Eclipse.
4. Open the file `FineCollectionService/src/main/java/dapr/fines/violation/KafkaViolationConsumer.java` in your code editor.
5. Comment out @KafkaLister annotation line
@ -193,7 +193,7 @@ You're going to start all the services now.
2. Open the terminal window and make sure the current folder is `VehicleRegistrationService`.
3. Enter the following command to run the VehicleRegistrationService with a Dapr sidecar:
3. Enter the following command to run the VehicleRegistrationService:
```console
mvn spring-boot:run
@ -208,17 +208,17 @@ You're going to start all the services now.
dapr run --app-id finecollectionservice --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --components-path ../dapr/components mvn spring-boot:run
```
6. Open a **new** terminal window and change the current folder to `TrafficControlService`.
1. Open a **new** terminal window and change the current folder to `TrafficControlService`.
7. Enter the following command to run the TrafficControlService with a Dapr sidecar:
2. Enter the following command to run the TrafficControlService with a Dapr sidecar:
```console
dapr run --app-id trafficcontrolservice --app-port 6000 --dapr-http-port 3600 --dapr-grpc-port 60000 --components-path ../dapr/components mvn spring-boot:run
```
8. Open a **new** terminal window and change the current folder to `Simulation`.
3. Open a **new** terminal window and change the current folder to `Simulation`.
9. Start the simulation:
4. Start the simulation:
```console
mvn spring-boot:run

Просмотреть файл

@ -0,0 +1,110 @@
---
title: Part 1 - Setup Azure Keyvault as a secrets store
parent: Use Azure Keyvault as a secrets store
has_children: false
nav_order: 1
---
# Part 1 - Setup Azure Key Vault as a secrets store
This bonus assignment is about using Azure Key Vault as a [secret store](https://docs.dapr.io/operations/components/setup-secret-store/). You will create the [Azure Key Vault secret store component](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/) provided by Dapr.
## Step 1: Create an Azure AD application
1. Open a terminal window.
1. Create an Azure AD application
```azurecli
az ad app create --display-name dapr-java-workshop-fine-collection-service
```
1. Get the application ID and note it down. You will need it in the next step.
```azurecli
az ad app list --display-name dapr-java-workshop-fine-collection-service --query [].appId -o tsv
```
1. Create the client secret using the following command and replace `<appId>` with the application ID you noted down in the previous step:
```azurecli
az ad app credential reset --id <appId> --years 2
```
Take note of the values above, which will be used in the Dapr component's metadta to allow Dapr to authenticate with Azure:
- `appId` is the value for `azureClientId`
- `password` is the value for `azureClientSecret`
- `tenant` is the value for `azureTenantId`
## Step 2: Create a Service Principal
1. Create a Service Principal using the following command and replace `<appId>` with the application ID you noted down in the previous step:
```azurecli
az ad sp create --id <appId>
```
1. Get the Service Principal ID and note it down. You will need it to assign the role to access the Key Vault.
```azurecli
az ad sp list --display-name dapr-java-workshop-fine-collection-service --query [].id -o tsv
```
## Step 3: Create an Azure Key Vault
1. Open a terminal window.
1. Create an Azure Key Vault
```azurecli
az keyvault create --name kv-dapr-java-workshop --resource-group dapr-workshop-java --location eastus --enable-rbac-authorization true
```
1. Get the id of the subscription and note it down. You will need it in the next step.
```azurecli
az account show --query id -o tsv
```
1. Assign a role using RBAC to the Azure AD application to access the Key Vault. The role "Key Vault Secrets User" is sufficient for this workshop. Replace `<servicePrincipalId>` with the Service Principal ID you noted down and `<subscriptionId>` with the value you noted in the previous step:
```azurecli
az role assignment create --role "Key Vault Secrets User" --assignee <servicePrincipalId> --scope "/subscriptions/<subscriptionid>/resourcegroups/dapr-workshop-java/providers/Microsoft.KeyVault/vaults/kv-dapr-java-workshop"
```
## Step 4: Create a secret in the Azure Key Vault
The service principal created in the previous steps has the role `Key Vault Secrets User` assigned. It means this service principal can only read secrets.
To create a secret in the Azure Key Vault, you can use the Azure Portal or the Azure CLI. In this workshop, we will use the Azure CLI. First you need to assign you the role of `Key Vault Secrets Officer` to be able to create secrets in the Key Vault. To know more about the different roles, see [Azure built-in roles for Key Vault data plane operations](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli#azure-built-in-roles-for-key-vault-data-plane-operations).
To assign to you the role of `Key Vault Secrets Officer`, follow these steps:
1. Open a terminal window.
1. Get your user id and note it down. You will need it in the next step.
```azurecli
az ad user show --id <your-email-address> --query id -o tsv
```
Replace `<your-email-address>` with your email address.
1. Assign you `Key Vault Secrets Officer` role:
```azurecli
az role assignment create --role "Key Vault Secrets Officer" --assignee <userId> --scope "/subscriptions/<subscriptionid>/resourcegroups/dapr-workshop-java/providers/Microsoft.KeyVault/vaults/kv-dapr-java-workshop"
```
Replace `<userId>` with the value you noted down in the previous step.
To create a secret in the Azure Key Vault, use the following command and replace `<secret-name>` and `<secret-value>` with the name and value of the secret you want to create:
```azurecli
az keyvault secret set --vault-name kv-dapr-java-workshop --name <secret-name> --value <secret-value>
```
## Step 5: Set the Azure Key Vault secrets store component
1. **Copy or Moive** this file `dapr/azure-keyvault-secretsstore.yam` to `dapr/components/` folder.
1. Open the copied file `dapr/components/azure-keyvault-secretsstore.yaml` in your code editor.
1. Set the following values in the metadata section of the component:
- `azureTenantId`: The value for `tenant` you noted down in step 1.
- `azureClientId`: The value for `appId` you noted down in step 1.
- `azureClientSecret`: The value for `password` you noted down in step 1.
{: .important }
> Certificate can be used instead of client secret, see [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).
>
> When deployed to Azure Kubernetes Service, the client secret is a kubernetes secret and not set in the component's YAML file. See the *Kubernetes* tab in *Configure the component* of [Azure Key Vault secret store](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/).
>
> When deployed to Azure Kubernetes Service or Azure Container Apps, managed identity can be used instead of client secret. See [Using Managed Service Identities](https://docs.dapr.io/developing-applications/integrations/azure/authenticating-azure/#using-managed-service-identities).

Просмотреть файл

@ -0,0 +1,128 @@
---
title: Retrieve a secret in the application
parent: Use Azure Keyvault as a secrets store
has_children: false
nav_order: 2
---
# Part 2 - Retrieve a secret in the application
Previously, you have created an Azure Key Vault and added the Dapr component. Now, you will use the secret in the application. If the setup of the Azure Key Vault is not done yet, please follow the instructions in `Part 1 - Setup Azure Key Vault as a secrets store`.
This bonus assignment is about using Azure Key Vault as a [secrets store](https://docs.dapr.io/operations/components/setup-secret-store/) for the `FineCollectionService` to get the license key.
## Step 1: Create a secret in the Azure Key Vault for the license key
1. Open a terminal window.
1. Create a secret in the Azure Key Vault for the license key:
```azurecli
az keyvault secret set --vault-name kv-dapr-java-workshop --name license-key --value HX783-5PN1G-CRJ4A-K2L7V
```
## Step 2: Use the secret in the application `FineCollectionService`
1. Open the file `FineCollectionService/src/main/java/dapr/fines/fines/DaprCalulator.java` in your code editor, and inspect it
1. It implements the `FineCalculator` interface, which is used by the `FineCollectionService` to calculate the fine for a car. The `FineCalculator` interface has a method `calculateFine` that takes the `excessSpeed` as input and returns the amount of the fine as output. If the excess speed is too high, it return `-1`.
The object `FineFines` that computes the fine requires a license Key. The license key is used to validate the license of the fine calculator. This `DaprFineCalculator` is getting the license key from the secrets store when the `FineCalculator` bean is created in the class `FineCollectionConfiguration`. The license key is stored in the secrets store with the name `license-key`.
```java
public class DaprFineCalculator implements FineCalculator {
private final String fineCalculatorLicenseKey;
private final FineFines fineFines;
public DaprFineCalculator(final DaprClient daprClient) {
if (daprClient == null) {
throw new IllegalArgumentException("daprClient");
}
final Map<String, String> licenseKeySecret = daprClient.getSecret("secretsstore", "license-key").block();
if (licenseKeySecret == null || licenseKeySecret.isEmpty()) {
throw new RuntimeException("'license-key' is not part of the secrets store.");
}
this.fineCalculatorLicenseKey = licenseKeySecret.get("license-key");
this.fineFines = new FineFines();
}
@Override
public int calculateFine(final int excessSpeed) {
return fineFines.calculateFine(this.fineCalculatorLicenseKey, excessSpeed);
}
}
```
1. Open the file `FineCollectionService/src/main/java/dapr/fines/FineCollectionConfiguration.java` in your code editor
1. **Comment out** the following lines as the license key is now retrieved from the secrets store instead of the environment variable:
```java
@Value("${finefines.license-key}")
private String fineCalculatorLicenseKey;
```
1. **Comment out** the following @Bean method that creates the bean `FineCalculator`:
```java
@Bean
public FineCalculator fineCalculator() {
return new DefaultFineCalculator(fineCalculatorLicenseKey);
}
```
1. **Uncomment** the following @Bean method that creates the bean `FineCalculator`:
```java
// @Bean
// public FineCalculator fineCalculator(final DaprClient daprClient) {
// return new DaprFineCalculator(daprClient);
// }
```
This method requires the `DaprClient` as input.
1. **Uncomment** the following @Bean method that creates the bean `DaprClient`:
```java
// @Bean
// public DaprClient daprClient() {
// return new DaprClientBuilder().build();
// }
```
## Step 3: Test the application
You're going to start all the services now.
1. Make sure no services from previous tests are running (close the command-shell windows).
2. Open the terminal window and make sure the current folder is `VehicleRegistrationService`.
3. Enter the following command to run the VehicleRegistrationService with a Dapr sidecar:
```console
mvn spring-boot:run
```
4. Open a **new** terminal window and change the current folder to `FineCollectionService`.
5. Enter the following command to run the FineCollectionService with a Dapr sidecar:
* Ensure you have run `dapr init` command prior to running the below command
```console
dapr run --app-id finecollectionservice --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --components-path ../dapr/components mvn spring-boot:run
```
6. Open a **new** terminal window and change the current folder to `TrafficControlService`.
7. Enter the following command to run the TrafficControlService:
```console
mvn spring-boot:run
```
8. Open a **new** terminal window and change the current folder to `Simulation`.
9. Start the simulation:
```console
mvn spring-boot:run
```
You should see the same logs as **Assignment 1**. Obviously, the behavior of the application is exactly the same as before.

Просмотреть файл

@ -0,0 +1,15 @@
---
title: Use Azure Keyvault as a secrets store
parent: Bonus Assignments
has_children: true
nav_order: 2
---
# Bonus Assigment: Use Azure Keyvault as a secrets store
This bonus assignment is about using Azure Key Vault as a [secret store](https://docs.dapr.io/operations/components/setup-secret-store/) for the `FineCollectionService`. You will use the [Azure Key Vault secret store component](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/) provided by Dapr.
The first part is the setup of the Azure Key Vault. The second part is the configuration of the `FineCollectionService` to use the Azure Key Vault as a secret store for the license key of the fine calculator. the third part is to use the secret store in the `FineCollectionService` and the `TrafficControllerService` to get the connection string for Azure Service Bus.
{: .note }
> The first part is a pre-requisite for the second and third part. The second and third part can be done in any order.