> ## Documentation Index
> Fetch the complete documentation index at: https://docs.futurex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate and test

> Procedural steps to validate and test certificate management across Minikube, Microk8s, and K3s environments.

If there are issues, visit

[**Troubleshooting**](../Appendices/Troubleshooting) to view different troubleshooting solutions.

## Files needed for each test

There are 3 files that need to be applied to each integration test:

-**Secret.yml**
This secret stores the CryptoHub integration-specific partition/application's API Key for use by the Futurex issuer to authenticate to CryptoHub. The partition/application must have the permission to upload a CSR and access the issuer policy.

* **Issuer.yml**
  A **Kubernetes Custom Resource Definition (CRD)** configuration file that defines a `CryptohubIssuer` or `CryptohubClusterIssuer`.
  Its primary function is to establish a bridge between the Kubernetes `cert-manager` add-on and the Futurex CryptoHub platform. It tells `cert-manager` exactly how to authenticate to and communicate with CryptoHub to request and issue trusted X.509 TLS certificates.
* **Cert.yml**
  A file describes the desired properties of a new certificate, triggering the internal generation of a CSR. In the `cert-manager` ecosystem, the file typically defines a Kubernetes `Certificate` resource.

The files pasted below are to be used as a template.

<Note>
  For the namespace, the `cert.yml`, `issuer.yml`, and `secret.yml` must be in the same namespace.
</Note>

<Note>
  Names of Kubernetes resources strictly follow `DNS Label Naming` (RFC 1035).
</Note>

**Secret.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: v1
kind: Secret
metadata:
  name: <secret-name> # The name applications and other YAML files use to find this Secret.
  namespace: <custom-namespace> # Namespace where this resource (e.g., Secret or Issuer) will be created.
stringData:
  apikey: "<partition_api_key>" # API key of the partition / role specific for this integration
```

**Issuer.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: certificate.k8s.futurex.com/v1
kind: CryptohubIssuer
metadata:
  name: <issuer-name> # Specify the name applications and other YAML files use to reference this issuer. 
  namespace: <custom-namespace> # Namespace where this resource (e.g., Secret or Issuer) will be created.
spec:
  uri: "<ip-of-CryptoHub>" # The IP address or hostname of Cryptohub
  policyId: "<issuance-policy-id>" # On CryptoHub, after right clicking the CA > Issuance Policy > Edit..., copy the UUID here. 
  apiKeySecret: "<secret-name>" # The name of the secret found in Secret.yml
  extensionProfile: "TLS Certificate"
  hashType: "SHA-256"
  #  debug: true
```

**Cert.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com  # The name of this Certificate resource.
  namespace: <custom-namespace> # Namespace where this Certificate resource will be created.
spec:
  secretName: <secret-name> # The name of the secret found in Secret.yml
  
  # --- Certificate Lifetime Settings ---
  duration: 2160h                 # Requested total lifespan of the certificate (e.g., 90 days).
  renewBefore: 360h               # How long before expiry (15 days) cert-manager should start renewal.
  
  isCA: false                     # Set to 'true' if the resulting certificate should be a CA certificate.
  commonName: example.com         # Deprecated: The main subject name. Preferred method is 'dnsNames'.
  
  # --- Private Key Configuration ---
  privateKey:
    algorithm: RSA
    encoding: PKCS1
    size: 2048                    # The size of the private key.
    
  usages:
    - server auth                 # Allows the certificate to be used for TLS servers (e.g., Ingress).
    - client auth                 # Allows the certificate to be used for client authentication.
    
  # --- Certificate Subject Details ---
  subject:
    organizations:
      - cert-manager
      
  dnsNames:
    - example.com                 # Primary DNS Subject Alternative Name (SAN).
    - www.example.com             # Additional DNS SAN.
    
  # Non-DNS SANs (optional)
  uris:
    - spiffe://cluster.local/ns/sandbox/sa/example
  ipAddresses:
    - 192.168.0.5
    
  # --- Issuer Reference (MANDATORY for Futurex Integration) ---
  issuerRef:
    name: <issuer-name> # Must match the name found in Issuer.yml.
    kind: <fx-crd-kind> # Must be the Kind defined by the Futurex Custom Resource (CRD). Either CryptohubIssuer or CryptohubClusterIssuer.
    group: certificate.k8s.futurex.com # The API Group defined by the Futurex CRD.
```

## Minikube

This section will validate the Kubernetes `cert-manager` integration with CryptoHub by setting up the files needed for `cert-manager` to establish communication with CryptoHub, send a certificate signing request (CSR), and, once approved, retrieve the signed CSR from the CryptoHub.

**Secret.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: v1
kind: Secret
metadata:
  name: <secret-name> # The name applications and other YAML files use to find this Secret.
  namespace: <custom-namespace> # Namespace where this resource (e.g., Secret or Issuer) will be created.
stringData:
  apikey: "<partition_api_key>" # API key of the partition / role specific for this integration
```

**Issuer.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: certificate.k8s.futurex.com/v1
kind: CryptohubIssuer
metadata:
  name: <issuer-name> # Specify the name applications and other YAML files use to reference this issuer. 
  namespace: <custom-namespace> # Namespace where this resource (e.g., Secret or Issuer) will be created.
spec:
  uri: "<ip-of-CryptoHub>" # The IP address or hostname of Cryptohub
  policyId: "<issuance-policy-id>" # On CryptoHub, after right clicking the CA > Issuance Policy > Edit..., copy the UUID here. 
  apiKeySecret: "<secret-name>" # The name of the secret found in Secret.yml
  extensionProfile: "TLS Certificate"
  hashType: "SHA-256"
  #  debug: true
```

**Cert.yml**

```yaml expandable lines wrap title="YAML" theme={null}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com  # The name of this Certificate resource.
  namespace: <custom-namespace> # Namespace where this Certificate resource will be created.
spec:
  secretName: <secret-name> # The name of the secret found in Secret.yml
  
  # --- Certificate Lifetime Settings ---
  duration: 2160h                 # Requested total lifespan of the certificate (e.g., 90 days).
  renewBefore: 360h               # How long before expiry (15 days) cert-manager should start renewal.
  
  isCA: false                     # Set to 'true' if the resulting certificate should be a CA certificate.
  commonName: example.com         # Deprecated: The main subject name. Preferred method is 'dnsNames'.
  
  # --- Private Key Configuration ---
  privateKey:
    algorithm: RSA
    encoding: PKCS1
    size: 2048                    # The size of the private key.
    
  usages:
    - server auth                 # Allows the certificate to be used for TLS servers (e.g., Ingress).
    - client auth                 # Allows the certificate to be used for client authentication.
    
  # --- Certificate Subject Details ---
  subject:
    organizations:
      - cert-manager
      
  dnsNames:
    - example.com                 # Primary DNS Subject Alternative Name (SAN).
    - www.example.com             # Additional DNS SAN.
    
  # Non-DNS SANs (optional)
  uris:
    - spiffe://cluster.local/ns/sandbox/sa/example
  ipAddresses:
    - 192.168.0.5
    
  # --- Issuer Reference (MANDATORY for Futurex Integration) ---
  issuerRef:
    name: <issuer-name> # Must match the name found in Issuer.yml.
    kind: <fx-crd-kind> # Must be the Kind defined by the Futurex Custom Resource (CRD). Either CryptohubIssuer or CryptohubClusterIssuer.
    group: certificate.k8s.futurex.com # The API Group defined by the Futurex CRD.
```

### Validation steps using the files

<Steps>
  <Step>
    Create a custom namespace for the **Secret**, **CryptohubIssuer**, and **Certificate**.

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl create namespace ch-cert-manager
    ```
  </Step>

  <Step>
    Copy and paste the contents in the templates above into appropriately named files, and edit the files to match the values for your specific use case using a tool like `nano` or `vim`.
    For this specific validation, the following files contains information to serve as an example:

    * **Secret.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: v1
    kind: Secret
    metadata:
      name: ch-hsm-credentials
      namespace: ch-cert-manager
    stringData:
      apikey: "Acy5M3VJttc3wR36PE_BNod4jPQngDwgbR527wJOya2qqTxtEQAA4MbuSy4aB56_iZCGUwvQtE6G6CA"
    ```

    * **Issuer.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: certificate.k8s.futurex.com/v1
    kind: CryptohubIssuer
    metadata:
      name: cryptohub-issuer
      namespace: ch-cert-manager
    spec:
      uri: "https://10.40.20.10/"
      policyId: "01d5bf1d-bcad-0000-0000-ebb402480751"
      apiKeySecret: "ch-hsm-credentials"
      extensionProfile: "TLS Certificate"
      hashType: "SHA-256"
      insecureSkipVerify: true # Needed for internal Futurex testing (can remove if posting)
      #  debug: true
    ```

    * **Cert.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: example-com  
      namespace: ch-cert-manager
    spec:
      secretName: ch-hsm-credential
      duration: 2160h                 
      renewBefore: 360h               
      isCA: false                     
      commonName: example.com         
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 2048          
      usages:
        - server auth         
        - client auth         
      subject:
        organizations:
          - cert-manager
      dnsNames:
        - example.com                 
        - www.example.com             
      uris:
        - spiffe://cluster.local/ns/sandbox/sa/example
      ipAddresses:
        - 192.168.0.5
      issuerRef:
        name: cryptohub-issuer
        kind: CryptohubIssuer
        group: certificate.k8s.futurex.com 
    ```
  </Step>

  <Step>
    Apply the files to create the Kubernetes resources.

    <Warning>
      The order of how the files are applied matters. The resources need to be created / updated in a specific sequence so that the `cert-manager` controller can successfully process them.

      The order is:

      1. Secret
      2. Issuer
      3. Certificate
    </Warning>

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl apply -f Secret.yml
    kubectl apply -f Issuer.yml
    kubectl apply -f Cert.yml
    ```
  </Step>

  <Step>
    If no errors arose, a CSR should automatically be created, ready to be signed. To check, run the following command:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl get certificaterequest -n ch-cert-manager
    ```

    <Note>
      The `-n` flag value should be the namespace that you have created.
    </Note>

    <Check>
      Successful output should like similar to:

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1                               cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   3m24s
      ```
    </Check>
  </Step>

  <Step>
    Use `cmctl` to approve the CSR. This will let the `cert-manager` controller that the request is valid and should proceed to be signed by the assigned issuer.

    ```shell expandable lines wrap title="Shell" theme={null}
    cmctl approve example-com-1 -n ch-cert-manager
    ```
  </Step>

  <Step>
    Login to CryptoHub with the appropriate identity that has the permission to sign the CSR.

    1. Go to **PKI and CA** > **PKI Signing Approvals**.
    2. Click on the **+** icon next to the approval group created for this integration.
    3. A new entry will appear, displaying the yellow paper with a pen, and a status column showing "Pending 0/x". The value 'x' indicates the total number of required approvals or identities that must approve the CSR before the signed certificate is issued.
    4. To view the details of the CSR, right-click it and select **Edit**.
    5. To approve or deny the CSR, either select the CSR and click on **Approve** or **Deny** on the bottom right or right-click on the CSR and select **Approve** or **Deny**.
    6. After approving the CSR, a box will appear describing the **User** that signed the CSR, the **Status** of the CSR, the **Time** that it was signed, and a **Message** box that the user can use to write an optional message.
    7. Select **\[ OK ]** for the approval to be issued.
  </Step>

  <Step>
    To validate if the signed certificate was received, go the terminal where Minikube was installed, and with the name of the `CertificateRequest` that was discovered earlier, run the command to find details about the approval process.

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl describe certificaterequest -n ch-cert-manager
    ```

    <Note>
      A positive output should look something similar to below:

      ```none expandable lines wrap title="None" theme={null}
      Events:
        Type     Reason          Age                    From                             Message
        ----     ------          ----                   ----                             -------
        Warning  RetryableError  11m                    cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: updated request id annotation
        Warning  RetryableError  6m55s (x253 over 11m)  cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: pending approval
        Normal   Issued          3m8s                   cryptohubissuer.k8s.futurex.com  Succeeded signing the CertificateRequest
      ```
    </Note>
  </Step>

  <Step>
    The validation process can be repeated with the second Futurex issuer type: `CryptohubClusterIssuer`

    This is done by editing:

    * `kind:` in **Issuer.yml**
    * `kind:` in **Cert.yml**, under `issuerRef`.
  </Step>
</Steps>

## Microk8s

### Validation steps using the files

<Steps>
  <Step>
    Create a custom namespace for the **Secret**, **CryptohubIssuer**, and **Certificate**

    ```shell expandable lines wrap title="Shell" theme={null}
    microk8s kubectl create namespace ch-cert-manager
    ```
  </Step>

  <Step>
    Copy and paste the contents in the templates above into appropiately named files, and edit the files to match the values for your specific use case using a tool like `nano` or `vim`.
    For this specific validation, the following files contains information to serve as an example:

    * **Secret.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: v1
    kind: Secret
    metadata:
      name: ch-hsm-credentials 
      namespace: ch-cert-manager
    stringData:
      apikey: "ASQ-Hlzgex7p3AldwN2joCGg4GOo-RaBpCENiaFBizR3P7BtEQAA4MbuSzLeu57eSX1NEUEK1pMWIH4"
    ```

    * **Issuer.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: certificate.k8s.futurex.com/v1
    kind: CryptohubIssuer
    metadata:
      name: cryptohub-issuer
      namespace: ch-cert-manager
    spec:
      uri: "https://10.40.20.10/"
      policyId: "01d5bf1d-bcad-0000-0000-ebb402480751"
      apiKeySecret: "ch-hsm-credentials"
      extensionProfile: "TLS Certificate"
      hashType: "SHA-256"
      insecureSkipVerify: true # Needed for internal Futurex testing (can remove if posting)
      #  debug: true
    ```

    * **Cert.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: example-com  
      namespace: ch-cert-manager
    spec:
      secretName: ch-hsm-credential
      duration: 2160h                 
      renewBefore: 360h               
      isCA: false                     
      commonName: example.com         
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 2048          
      usages:
        - server auth         
        - client auth         
      subject:
        organizations:
          - cert-manager
      dnsNames:
        - example.com                 
        - www.example.com             
      uris:
        - spiffe://cluster.local/ns/sandbox/sa/example
      ipAddresses:
        - 192.168.0.5
      issuerRef:
        name: cryptohub-issuer
        kind: CryptohubIssuer
        group: certificate.k8s.futurex.com 
    ```
  </Step>

  <Step>
    Apply the files to create the Kubernetes resources.

    <Warning>
      The order of how the files are applied matters. The resources need to be created / updated in a specific sequence so that the `cert-manager` controller can successfully process them.

      The order is:

      1. Secret
      2. Issuer
      3. Certificate
    </Warning>

    ```shell expandable lines wrap title="Shell" theme={null}
    microk8s kubectl apply -f Secret.yml
    microk8s kubectl apply -f Issuer.yml
    microk8s kubectl apply -f Cert.yml
    ```
  </Step>

  <Step>
    If no errors arose, a CSR should automatically be created, ready to be signed. To check, run the following command:

    ```shell expandable lines wrap title="Shell" theme={null}
    microk8s kubectl get certificaterequest -n ch-cert-manager
    ```

    <Note>
      The `-n` flag value should be the namespace that you have created.
    </Note>

    <Check>
      Successful output should like similar to:

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1                               cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   3m24s
      ```
    </Check>
  </Step>

  <Step>
    Login to CryptoHub with the appropriate identity that has the permission to sign the CSR.

    1. Go to **PKI and CA** > **PKI Signing Approvals**.
    2. Click on the **+** icon next to the approval group created for this integration.
    3. A new entry will appear, displaying the yellow paper with a pen, and a status column showing "Pending 0/x". The value 'x' indicates the total number of required approvals or identities that must approve the CSR before the signed certificate is issued.
    4. To view the details of the CSR, right-click it and select **Edit**.
    5. To approve or deny the CSR, either select the CSR and click on **Approve** or **Deny** on the bottom right or right-click on the CSR and select **Approve** or **Deny**.
    6. After approving the CSR, a box will appear describing the **User** that signed the CSR, the **Status** of the CSR, the **Time** that it was signed, and a **Message** box that the user can use to write an optional message.
    7. Select **\[ OK ]** for the approval to be issued.
  </Step>

  <Step>
    To validate if the signed certificate was received, go the terminal where Minikube was installed, and with the name of the `CertificateRequest` that was discovered earlier, run the command to find details about the approval process

    ```shell expandable lines wrap title="Shell" theme={null}
    microk8s kubectl describe certificaterequest -n ch-cert-manager
    ```

    <Note>
      A positive output should look something similar to below:

      ```none expandable lines wrap title="None" theme={null}
      Events:
        Type     Reason          Age                    From                             Message
        ----     ------          ----                   ----                             -------
        Warning  RetryableError  11m                    cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: updated request id annotation
        Warning  RetryableError  6m55s (x253 over 11m)  cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: pending approval
        Normal   Issued          3m8s                   cryptohubissuer.k8s.futurex.com  Succeeded signing the CertificateRequest
      ```
    </Note>
  </Step>

  <Step>
    The validation process can be repeated with the second Futurex issuer type: `CryptohubClusterIssuer`

    This is done by editing:

    * `kind:` in **Issuer.yml**
    * `kind:` in **Cert.yml**, under `issuerRef`.
  </Step>
</Steps>

## K3s - Single device (Docker)

### Validation steps using the files

<Steps>
  <Step>
    Create a custom namespace for the **Secret**, **CryptohubIssuer**, and **Certificate**.

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl create namespace ch-cert-manager
    ```
  </Step>

  <Step>
    On the machine hosting the `k3s-server`, copy and paste the contents in the templates above into appropiately named files, and edit the files to match the values for your specific use case using a tool like `nano` or `vim`.
    For this specific validation, the following files contains information to serve as an example

    * **Secret.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: v1
    kind: Secret
    metadata:
      name: ch-hsm-credentials
      namespace: ch-cert-manager
    stringData:
      apikey: "Acy5M3VJttc3wR36PE_BNod4jPQngDwgbR527wJOya2qqTxtEQAA4MbuSy4aB56_iZCGUwvQtE6G6CA"
    ```

    * **Issuer.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: certificate.k8s.futurex.com/v1
    kind: CryptohubIssuer
    metadata:
      name: cryptohub-issuer
      namespace: ch-cert-manager
    spec:
      uri: "https://10.40.20.10/"
      policyId: "01d5bf1d-bcad-0000-0000-ebb402480751"
      apiKeySecret: "ch-hsm-credentials"
      extensionProfile: "TLS Certificate"
      hashType: "SHA-256"
      insecureSkipVerify: true # Needed for internal Futurex testing (can remove if posting)
      #  debug: true
    ```
  </Step>

  <Step>
    Apply the files to create the Kubernetes resources.

    <Warning>
      The order of how the files are applied matters. The resources need to be created / updated in a specific sequence so that the `cert-manager` controller can successfully process them.

      The order is:

      1. Secret
      2. Issuer
    </Warning>

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl apply -f Secret.yml
    kubectl apply -f Issuer.yml
    ```
  </Step>

  <Step>
    Copy the `k3s.yaml` file that was created in the **Install the Kubernetes tool** page to the agent's filesystem.

    ```shell expandable lines wrap title="Shell" theme={null}
    docker cp ./k3s.yaml k3s-agent-1:/
    ```
  </Step>

  <Step>
    Create a terminal session for the agent.

    ```shell expandable lines wrap title="Shell" theme={null}
    docker exec -it k3s-agent-1 sh
    ```
  </Step>

  <Step>
    On the `k3s-agent-1` terminal session, edit the `k3s.yaml` file to change the hostname of the server from `127.0.0.1` or whatever the default value is to the given server hostname or server IP address.

    ```shell expandable lines wrap title="Shell" theme={null}
    vi k3s.yaml
    ```

    <Note>
      The server's Docker hostname can be used.
    </Note>

    ```none expandable lines wrap title="None" theme={null}
    server: https://k3s-server:6443
    ```
  </Step>

  <Step>
    On the `k3s-agent-1` terminal session, update the kubectl environment variable for the agent.

    ```shell expandable lines wrap title="Shell" theme={null}
    export KUBECONFIG=k3s.yaml
    ```
  </Step>

  <Step>
    On the `k3s-agent-1` terminal session, copy and paste the contents in the cert template above into an appropriately named file (e.g., `Cert.yml`) , and edit the files to match the values for your specific use case using `vi` tool.
    For this specific validation, the following file contains information to serve as an example.

    ```shell expandable lines wrap title="Shell" theme={null}
    vi Cert.yml
    ```

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: example-com
      namespace: ch-cert-manager
    spec:
      secretName: ch-hsm-credential
      duration: 2160h
      renewBefore: 360h
      isCA: false
      commonName: example.com
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 2048
      usages:
        - server auth
        - client auth
      subject:
        organizations:
          - cert-manager
      dnsNames:
        - example.com
        - www.example.com
      uris:
        - spiffe://cluster.local/ns/sandbox/sa/example
      ipAddresses:
        - 192.168.0.5
      issuerRef:
        name: cryptohub-issuer
        kind: CryptohubIssuer
        group: certificate.k8s.futurex.com
    ```
  </Step>

  <Step>
    On the `k3s-agent-1` terminal session, apply the certificate using kubectl:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl apply -f cert.yml
    ```
  </Step>

  <Step>
    A CSR should automatically be created, ready to be approved by `cmctl`. On a terminal connected to `k3s-server`, run the following command to check if the CSR was generated:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl get certificaterequest -n ch-cert-manager example-com-1
    ```

    <Note>
      The `-n` flag value should be the namespace that you have created.
    </Note>

    <Check>
      Successful output should like similar to:

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1                               cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   3m24s
      ```
    </Check>
  </Step>

  <Step>
    Approve the request using `cmctl` so that Kubernetes API can send the certificate over to CryptoHub.

    ```shell expandable lines wrap title="Shell" theme={null}
    cmctl approve -n ch-cert-manager example-com-1
    ```

    <Check>
      Rerun the `get certificaterequest` command and the `APPROVED` column should be updated to True, and `READY` to False

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1   True                False   cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   5m23s
      ```
    </Check>
  </Step>

  <Step>
    Login into CryptoHub with the appropriate identity that has the permission to sign the CSR.

    1. Go to **PKI and CA** > **PKI Signing Approvals**.
    2. Click on the **+** icon next to the approval group created for this integration.
    3. A new entry will appear, displaying the yellow paper with a pen, and a status column showing "Pending 0/x". The value 'x' indicates the total number of required approvals or identities that must approve the CSR before the signed certificate is issued.
    4. To view the details of the CSR, right-click it and select **Edit**.
    5. To approve or deny the CSR, either select the CSR and click on **Approve** or **Deny** on the bottom right or right-click on the CSR and select **Approve** or **Deny**.
    6. After approving the CSR, a box will appear describing the **User** that signed the CSR, the **Status** of the CSR, the **Time** that it was signed, and a **Message** box that the user can use to write an optional message.
    7. Select **\[ OK ]** for the approval to be issued.
  </Step>

  <Step>
    To validate if the signed certificate was received, on the `k3s-server` run:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl describe certificaterequest -n ch-cert-manager example-com-1
    ```

    <Check>
      A positive output should look something similar to below:

      ```none expandable lines wrap title="None" theme={null}
      Events:
        Type     Reason          Age                    From                             Message
        ----     ------          ----                   ----                             -------
        Warning  RetryableError  11m                    cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: updated request id annotation
        Warning  RetryableError  6m55s (x253 over 11m)  cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: pending approval
        Normal   Issued          3m8s                   cryptohubissuer.k8s.futurex.com  Succeeded signing the CertificateRequest
      ```
    </Check>
  </Step>

  <Step>
    The validation process can be repeated with the second Futurex issuer type: `CryptohubClusterIssuer`

    This is done by editing:

    * `kind:` in **Issuer.yml**
    * `kind:` in **Cert.yml**, under `issuerRef`.
  </Step>
</Steps>

## K3s - Multidevice

### Validation steps using the files

<Steps>
  <Step>
    Create a custom namespace for the **Secret**, **CryptohubIssuer**, and **Certificate**.

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl create namespace ch-cert-manager
    ```
  </Step>

  <Step>
    On the server machine, copy and paste the contents in the templates above into appropiately named files, and edit the files to match the values for your specific use case using a tool like `nano` or `vim`.
    For this specific validation, the following files contains information to serve as an example

    * **Secret.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: v1
    kind: Secret
    metadata:
      name: ch-hsm-credentials
      namespace: ch-cert-manager
    stringData:
      apikey: "Acy5M3VJttc3wR36PE_BNod4jPQngDwgbR527wJOya2qqTxtEQAA4MbuSy4aB56_iZCGUwvQtE6G6CA"
    ```

    * **Issuer.yml**

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: certificate.k8s.futurex.com/v1
    kind: CryptohubIssuer
    metadata:
      name: cryptohub-issuer
      namespace: ch-cert-manager
    spec:
      uri: "https://10.40.20.10/"
      policyId: "01d5bf1d-bcad-0000-0000-ebb402480751"
      apiKeySecret: "ch-hsm-credentials"
      extensionProfile: "TLS Certificate"
      hashType: "SHA-256"
      insecureSkipVerify: true # Needed for internal Futurex testing (can remove if posting)
      #  debug: true
    ```
  </Step>

  <Step>
    Apply the files to create the Kubernetes resources.

    <Warning>
      Important: The order of how the files are applied matters. The resources need to be created / updated in a specific sequence so that the `cert-manager` controller can successfully process them.

      The order is:

      1. Secret
      2. Issuer
    </Warning>

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl apply -f Secret.yml
    kubectl apply -f Issuer.yml
    ```
  </Step>

  <Step>
    Copy the `k3s.yaml` from the server machine to the worker machine. The example below uses secure copy, `scp`.

    ```shell expandable lines wrap title="Shell" theme={null}
    scp /path/to/k3s.yaml <Worker_User>:<Worker_IP>:/path/to/copy/to
    ```
  </Step>

  <Step>
    Edit the `k3s.yaml` file on the worker machine to change the hostname of the server from the default value to the the server hostname or server IP address.

    ```shell expandable lines wrap title="Shell" theme={null}
    vi k3s.yaml
    ```

    ```none expandable lines wrap title="None" theme={null}
    server: https://<Server_Hostname_Or_IP>:6443
    ```
  </Step>

  <Step>
    On the worker machine, update the kubectl environment variable

    ```shell expandable lines wrap title="Shell" theme={null}
    export KUBECONFIG=k3s.yaml
    ```
  </Step>

  <Step>
    On the worker machine, copy and paste the contents in the cert template above into an appropriately named file (e.g., `Cert.yml`) , and edit the files to match the values for your specific use case using `vi` tool.

    For this specific validation, the following file contains information to serve as an example:

    ```shell expandable lines wrap title="Shell" theme={null}
    vi Cert.yml
    ```

    ```yaml expandable lines wrap title="YAML" theme={null}
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: example-com
      namespace: ch-cert-manager
    spec:
      secretName: ch-hsm-credential
      duration: 2160h
      renewBefore: 360h
      isCA: false
      commonName: example.com
      privateKey:
        algorithm: RSA
        encoding: PKCS1
        size: 2048
      usages:
        - server auth
        - client auth
      subject:
        organizations:
          - cert-manager
      dnsNames:
        - example.com
        - www.example.com
      uris:
        - spiffe://cluster.local/ns/sandbox/sa/example
      ipAddresses:
        - 192.168.0.5
      issuerRef:
        name: cryptohub-issuer
        kind: CryptohubIssuer
        group: certificate.k8s.futurex.com
    ```
  </Step>

  <Step>
    On the worker machine, apply the certificate using kubectl on the worker machine:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl apply -f cert.yml
    ```
  </Step>

  <Step>
    A CSR should automatically be created, ready to be approved by `cmctl`. On the server machine, run the following command to check if the CSR was generated:

    ```shell expandable lines wrap title="Shell" theme={null}
    kubectl get certificaterequest -n ch-cert-manager example-com-1
    ```

    <Note>
      The `-n` flag value should be the namespace that you have created.
    </Note>

    <Check>
      Successful output should like similar to:

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1                               cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   3m24s
      ```
    </Check>
  </Step>

  <Step>
    On the server mahcine, approve the request using `cmctl` so that Kubernetes API can send the certificate over to CryptoHub.

    ```shell expandable lines wrap title="Shell" theme={null}
    cmctl approve -n ch-cert-manager example-com-1
    ```

    <Check>
      Rerun the `get certificaterequest` command and the `APPROVED` column should be updated to True, and `READY` to False

      ```none expandable lines wrap title="None" theme={null}
      NAME            APPROVED   DENIED   READY   ISSUER             REQUESTER                                         AGE
      example-com-1   True                False   cryptohub-issuer   system:serviceaccount:cert-manager:cert-manager   5m23s
      ```
    </Check>
  </Step>

  <Step>
    Login into CryptoHub with the appropriate identity that has the permission to sign the CSR.

    1. Go to **PKI and CA** > **PKI Signing Approvals**.
    2. Click on the **+** icon next to the approval group created for this integration.
    3. A new entry will appear, displaying the yellow paper with a pen, and a status column showing "Pending 0/x". The value 'x' indicates the total number of required approvals or identities that must approve the CSR before the signed certificate is issued.
    4. To view the details of the CSR, right-click it and select **Edit**.
    5. To approve or deny the CSR, either select the CSR and click on **Approve** or **Deny** on the bottom right or right-click on the CSR and select **Approve** or **Deny**.
    6. After approving the CSR, a box will appear describing the **User** that signed the CSR, the **Status** of the CSR, the **Time** that it was signed, and a **Message** box that the user can use to write an optional message.
    7. Select **\[ OK ]** for the approval to be issued.
  </Step>

  <Step>
    To validate if the signed certificate was received, on the server machine run

    ```shell expandable lines wrap title="Shell" theme={null}
    microk8s kubectl describe certificaterequest -n ch-cert-manager
    ```

    <Note>
      A positive output should look something similar to below:

      ```none expandable lines wrap title="None" theme={null}
      Events:
        Type     Reason          Age                    From                             Message
        ----     ------          ----                   ----                             -------
        Warning  RetryableError  11m                    cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: updated request id annotation
        Warning  RetryableError  6m55s (x253 over 11m)  cryptohubissuer.k8s.futurex.com  Signing still in progress. Reason: Signing still in progress. Reason: pending approval
        Normal   Issued          3m8s                   cryptohubissuer.k8s.futurex.com  Succeeded signing the CertificateRequest
      ```
    </Note>
  </Step>

  <Step>
    The validation process can be repeated with the second Futurex issuer type: `CryptohubClusterIssuer`

    This is done by editing:

    * `kind:` in **Issuer.yml**
    * `kind:` in **Cert.yml**, under `issuerRef`.
  </Step>
</Steps>
