Infisical - Open Source SecretOps - Kubernetes Setup
Tags: infisical, kubernetes, opensource, secretops
Published: 2023-08-17 17:21:51

> In this article, we will talk about Infisical, an open-source secret management tool and how we can setup on a local Kubernetes cluster

## Introduction

* An open-source, end-to-end secret management platform
    
* Enables teams to easily manage and sync their environment variables, API keys, secrets and other configurations
    

## Features

* Intuitive dashboard
    
* Client SDK's
    
* Infisical CLI
    
* Native platform integrations
    
* Automatic Kubernetes deployment secret reloads
    
* Complete control of data when hosted by ourself
    
* Secret versioning
    
* Point-in-Time recovery
    
* Role-based access control
    
* Secret scanning and leak prevention
    
* Effortless on-premise deployment
    

## Prerequisites

* kubectl  
    Check my article to install [kubectl](https://iamunnip.hashnode.dev/kubectl-installation-ubuntu-windows)
    
    ```bash
    $ kubectl version --client --short
    Client Version: v1.27.4
    Kustomize Version: v5.0.1
    ```
    
* Helm  
    Check my article to install [Helm](https://iamunnip.hashnode.dev/helm-installation-ubuntu-windows)
    
    ```bash
    $ helm version
    version.BuildInfo{Version:"v3.12.1", GitCommit:"f32a527a060157990e2aa86bf45010dfb3cc8b8d", GitTreeState:"clean", GoVersion:"go1.20.4"}
    ```
    
* Kubernetes cluster  
    For this demo, I'm using [Rancher Desktop](https://docs.rancherdesktop.io/getting-started/installation/) on Windows
    
    ```bash
    $ kubectl get nodes
    
    NAME              STATUS   ROLES                  AGE   VERSION
    rancher-desktop   Ready    control-plane,master   27s   v1.27.4+k3s1
    ```
    

## Installation

* Add the Infisical Helm repository
    
    ```bash
    $ helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/' 
      
    $ helm repo update
    ```
    
* Install Infisical using the below command.  
    It will install all the necessary components in the infisical namespace and also install Nginx ingress controller
    
    ```bash
    $ helm install -n infisical infisical infisical-helm-charts/infisical --set ingress.nginx.enabled=true --create-namespace
    
    NAME: infisical
    LAST DEPLOYED: Thu Aug 17 19:43:06 2023
    NAMESPACE: infisical
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    ```
    
* Check the status of the components and the load balancer service created by Nginx ingress controller  
    Copy the Load Balancer IP, we will need it in the next step
    
    ```bash
    $ kubectl -n infisical get pods
    
    NAME                                                  READY   STATUS    RESTARTS   AGE
    infisical-frontend-8588c9f65-sxz8d                    1/1     Running   0          3m19s
    infisical-frontend-8588c9f65-nsnjr                    1/1     Running   0          3m19s
    mongodb-0                                             1/1     Running   0          3m19s
    infisical-backend-6777b66f58-79d84                    1/1     Running   0          3m19s
    infisical-backend-6777b66f58-g2fwb                    1/1     Running   0          3m19s
    infisical-ingress-nginx-controller-7785998dc6-lqxgk   1/1     Running   0          3m19s
    ```
    
    ```bash
    $ kubectl -n infisical get svc
    
    NAME                                           TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                      AGE
    infisical-backend                              ClusterIP      10.43.203.3     <none>           4000/TCP                     9m47s
    infisical-frontend                             ClusterIP      10.43.41.186    <none>           3000/TCP                     9m47s
    infisical-ingress-nginx-controller-admission   ClusterIP      10.43.42.222    <none>           443/TCP                      9m47s
    mongodb                                        ClusterIP      10.43.112.139   <none>           27017/TCP                    9m47s
    infisical-ingress-nginx-controller             LoadBalancer   10.43.63.38     172.31.134.241   80:30035/TCP,443:31538/TCP   9m47s
    ```
    

## Initial Setup

* In our local setup, we are skipping SMTP configuration and accessing the dashboard via the LoadBalancer IP address http://172.31.134.241/signup
You can also set up the hostname using `ingress.hostName=<your-hostname>` option during the installation
 
* Create an account for the administrator by clicking the "Continue with Email" option
    
    
![infisical-1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5r0r7tfs0lzpzqg4y5a.png)
    
* Enter your email id and click the "Get Started" option
    
    
![infisical-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpl3e9wjxom5jxlvb8j5.png)
    
* Enter the details accordingly and click "Sign Up" option
    
    
![infisical-3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x4b51m4pthu3277h9s2o.png)
    
* Once you sign up, you will need to download "Emergency Kit" and save it somewhere safe. If you get locked out of your account, we can use this emergency kit to unlock it
    
    
![infisical-4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u51rkcoukpsilgiz156q.png)
    
* Now we are redirected to the homepage of Infisical
    
    
![infisical-5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa0v2rlu7dr47n522tp2.png)
    

## Configuration

* Create a new project by clicking the "Add New Project" button from the dashboard and name your project "MyApp"
    
    
![infisical-6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avtdlr9ebl3t925n6yvq.png)
    
* Once our project is created, we will get an interface like below. Here we can see different environments like Development, Staging and Production.  
    We are going to add the secrets in the Development environment by clicking the "Go to Development" option
    
    
![infisical-7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71ckjq96w3z5ifziyhbx.png)
    
* We can copy secrets from other environments, upload env files etc. We can create a new secret by clicking the "Add a new secret" option
    
    
![infisical-8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpggde35rcpjvwvcghom.png)
    
* Add the required secrets and save the changes
    
    
![infisical-9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hu9njkrrhgtuqri1ysc.png)
    

## Secrets Operator Setup

* First, we need to generate a Service Token from our project settings
    
    
![infisical-10](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ps4xnmgt8s0dzmpxkp1.png)
    
* Select the "Create token" option and enter a name for the service token.  
    Select the environment, secrets path, expiration and permissions according to your use case and click on "Create" option
    
    
![infisical-11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/db61e69tn4gt9apxod3d.png)
    
* Once the service token is created, copy and save it somewhere safe. We need this token to configure the secrets operator
    
    
![infisical-12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfuhpwn75fp1jtad8zjd.png)
    
* Back in our Kubernetes cluster, we need to install and configure the Infisical secrets operator to sync our secrets to the cluster
    
    ```bash
    $ helm install -n infisical infisical-secrets-operator infisical-helm-charts/secrets-operator
    
    NAME: infisical-secrets-operator
    LAST DEPLOYED: Thu Aug 17 21:05:56 2023
    NAMESPACE: infisical
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None
    ```
    
* Check the infisical namespace, we can see a secret controller manager pod is created and it's up and running
    
    ```bash
    $ kubectl -n infisical get pods
    
    NAME                                                  READY   STATUS    RESTARTS   AGE
    infisical-frontend-8588c9f65-sxz8d                    1/1     Running   0          84m
    infisical-frontend-8588c9f65-nsnjr                    1/1     Running   0          84m
    mongodb-0                                             1/1     Running   0          84m
    infisical-backend-6777b66f58-79d84                    1/1     Running   0          84m
    infisical-backend-6777b66f58-g2fwb                    1/1     Running   0          84m
    infisical-ingress-nginx-controller-7785998dc6-lqxgk   1/1     Running   0          84m
    infisical-secre-controller-manager-56c6f9b6d-lqk2v    2/2     Running   0          100s
    ```
    
* Create a new namespace for our application
    
    ```bash
    $ kubectl create ns myapp
    
    namespace/myapp created
    ```
    
* Create a Kubernetes secret containing the Service Token
    
    ```bash
    $ kubectl -n myapp create secret generic myapp-service-token --from-literal=infisicalToken=st.64de3f83a96c27c805827382.a7acb98a535125353af9135009f9b974.3d41003562f52a730823347dd4a01f96
    
    secret/myapp-service-token created
    ```
    
    ```bash
    $ kubectl -n myapp get secrets
    
    NAME                  TYPE     DATA   AGE
    myapp-service-token   Opaque   1      25s
    ```
    
* Now we can sync our secrets to our cluster by creating an InfisicalSecret CRD
    
    ```bash
    apiVersion: secrets.infisical.com/v1alpha1
    kind: InfisicalSecret
    metadata:
      name: myapp-infisical-secret
      namespace: myapp
    spec:
      hostAPI: http://infisical-backend.infisical.svc.cluster.local:4000/api
      resyncInterval: 10
      authentication:
        serviceToken:
          serviceTokenSecretReference:
            secretName: myapp-service-token
            secretNamespace: myapp
          secretsScope:
            envSlug: dev
            secretsPath: "/"
      managedSecretReference:
        secretName: myapp-managed-secret
        secretNamespace: myapp
    ```
    
    ```bash
    $ kubectl apply -f myapp-infisical-secret.yml
    infisicalsecret.secrets.infisical.com/myapp-infisical-secret created
    ```
    
* Once it's created, check the status of the CRD
    
    From the status, we can see our secrets are synced to our cluster
    
    ```bash
    $ kubectl -n myapp get infisicalsecrets
    
    NAME                     AGE
    myapp-infisical-secret   42s
    ```
    
    ```bash
    $ kubectl -n myapp describe infisicalsecrets myapp-infisical-secret
    
    Name:         myapp-infisical-secret
    Namespace:    myapp
    Labels:       <none>
    Annotations:  <none>
    API Version:  secrets.infisical.com/v1alpha1
    Kind:         InfisicalSecret
    Metadata:
      Creation Timestamp:  2023-08-17T16:07:04Z
      Generation:          1
      Resource Version:    4927
      UID:                 bb156757-1528-4827-afe9-09916fcd4372
    Spec:
      Authentication:
        Service Token:
          Secrets Scope:
            Env Slug:      dev
            Secrets Path:  /
          Service Token Secret Reference:
            Secret Name:       myapp-service-token
            Secret Namespace:  myapp
      Host API:                http://infisical-backend.infisical.svc.cluster.local:4000/api
      Managed Secret Reference:
        Secret Name:       myapp-managed-secret
        Secret Namespace:  myapp
      Resync Interval:     10
    Status:
      Conditions:
        Last Transition Time:  2023-08-17T16:07:04Z
        Message:               Infisical controller has located the Infisical token in provided Kubernetes secret
        Reason:                OK
        Status:                True
        Type:                  secrets.infisical.com/LoadedInfisicalToken
        Last Transition Time:  2023-08-17T16:07:05Z
        Message:               Infisical controller has started syncing your secrets
        Reason:                OK
        Status:                True
        Type:                  secrets.infisical.com/ReadyToSyncSecrets
        Last Transition Time:  2023-08-17T16:07:05Z
        Message:               Infisical has found 0 deployments which are ready to be auto redeployed when secrets change
        Reason:                OK
        Status:                True
        Type:                  secrets.infisical.com/AutoRedeployReady
    Events:                    <none>
    ```
    
* We can verify the secrets have been synced to our cluster by checking the myapp-managed-secret
    
    ```bash
    $ kubectl -n myapp get secrets myapp-managed-secret
    
    NAME                   TYPE     DATA   AGE
    myapp-managed-secret   Opaque   4      5m16s
    ```
    
    ```bash
    $ kubectl -n myapp describe secrets myapp-managed-secret
    
    Name:         myapp-managed-secret
    Namespace:    myapp
    Labels:       <none>
    Annotations:  secrets.infisical.com/version: W/"a5a-hBx83Z5L+nuphYXlN17htm8jAjo"
    
    Type:  Opaque
    
    Data
    ====
    MYSQL_HOST:      9 bytes
    MYSQL_PASSWORD:  13 bytes
    MYSQL_PORT:      4 bytes
    MYSQL_DATABASE:  13 bytes
    ```
    

## Application Deployment

* Deploy a sample Nginx application using the below manifest file  
    The annotation `secrets.infisical.com/auto-reload: "true"` ensures that it automatically redeploys when managed secrets are changed
    
    ```bash
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
      namespace: myapp
      labels:
        app: myapp
      annotations: 
        secrets.infisical.com/auto-reload: "true"
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: maypp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: nginx:1.25.2
            envFrom:
            - secretRef:
                name: myapp-managed-secret
            ports:
            - containerPort: 80
    ```
    
    ```bash
    $ kubectl apply -f .\myapp-deployment.yml
    deployment.apps/myapp created
    ```
    
* Once our application is up and running, exec into the pod and list the environment variables to view our secrets
    
    ```bash
    $ kubectl -n myapp get pods
    
    NAME                     READY   STATUS    RESTARTS   AGE
    myapp-77c586c9ff-5xsxv   1/1     Running   0          48s
    ```
    
    ```bash
    $ kubectl -n myapp exec -it myapp-77c586c9ff-5xsxv -- bash
    
    root@myapp-77c586c9ff-5xsxv:/# env | grep -i MYSQL
    MYSQL_PORT=3306
    MYSQL_PASSWORD=mysqlPassword
    MYSQL_HOST=mysqlHost
    MYSQL_DATABASE=mysqlDatabase
    ```
    
* That's all for now
    

## Reference

[https://infisical.com/docs/integrations/platforms/kubernetes](https://infisical.com/docs/integrations/platforms/kubernetes)

[https://docs.rancherdesktop.io/getting-started/installation/](https://docs.rancherdesktop.io/getting-started/installation/)