# Deploy cert-manager

To secure your NGINX ingress controller, you'll need SSL/TLS certificates. You can either:

* Use a **Let's Encrypt** certificate (via **Cert-Manager**).
* Use a custom certificate (if you already have an SSL certificate and private key)

You use a **Let's Encrypt** certificate via cert-manager to do the work with Kubernetes to request a certificate and respond to the challenge to validate it.&#x20;

You can install **Cert-Manager** using Helm and configure it to issue SSL certificates from **Let's Encrypt**.

In `resources` folder, create a new `certmanager.ts` and add the below code:

```typescript
import * as k8s from "@pulumi/kubernetes";
import * as pulumi from "@pulumi/pulumi";
import { config } from "../config";

export const aksClusterIssuer = (k8sProvider) => {
    // Create a namespace for Cert-manager
    const certManagerNamespace = new k8s.core.v1.Namespace("cert-manager", {
        metadata: {
            name: "cert-manager",
        },
    }, { provider: k8sProvider });

    // Install Cert-manager using Helm
    const cert = new k8s.helm.v4.Chart("cert-manager", {
        chart: "cert-manager",
        version: "1.15.3",
        repositoryOpts: {
            repo: "https://charts.jetstack.io",
        },
        namespace: certManagerNamespace.metadata.name,
        values: {
            installCRDs: true
        },
    }, { transformations: [
        // Ignore changes that will be overwritten by the deployment.
        // https://www.pulumi.com/registry/packages/kubernetes/how-to-guides/managing-resources-with-server-side-apply/#handle-field-conflicts-on-existing-resources
        args => {
            if (args.type === "kubernetes:admissionregistration.k8s.io/v1:ValidatingWebhookConfiguration" ||
                args.type === "kubernetes:admissionregistration.k8s.io/v1:MutatingWebhookConfiguration") {
                return {
                    props: args.props,
                    opts: pulumi.mergeOptions(args.opts, {
                        ignoreChanges: ["metadata.annotations.template", "webhooks[*].clientConfig"],
                    })
                }
            }
            return undefined;
        }
    ], provider: k8sProvider });

    // Create a ClusterIssuer for Let's Encrypt
    const letsEncryptIssuer = new k8s.apiextensions.CustomResource("letsencrypt-issuer", {
        apiVersion: "cert-manager.io/v1",
        kind: "Issuer",
        metadata: {
            name: "letsencrypt-staging",
            namespace: config.appNamespace
        },
        spec: {
            acme: {
                server: "https://acme-staging-v02.api.letsencrypt.org/directory",
                email: config.letenscriptEmail,
                privateKeySecretRef: {
                    name: "letsencrypt-staging",
                },
                solvers: [{
                    http01: {
                        ingress: {
                            ingressClassName: "nginx",
                        },
                    },
                }],
            },
        },
    }, { provider: k8sProvider, dependsOn: cert });

    return letsEncryptIssuer;
}
```

Make the changes from `index.ts` file that includes the code to create cert manager and the cluster issuer:

```typescript
...
import { aksClusterIssuer } from "./resources/certmanager";
...

// Set Up Cert-Manager for Automatic Let's Encrypt Certificates
const letsEncryptIssuer = aksClusterIssuer(provider);

export const resourceGroupName = resourceGroup.name;
```

Deploy the resource again with the command:

```
pulumi up
```

### Verify the Cluster Issuer

When it is complete, you can check if the (Cluster)Issuer you're using is in a ready state:

```
$kubectl get issuers  -n apps
NAME                  READY   AGE
letsencrypt-staging   True    109m
```

And check the status using `kubectl describe:`

```
$kubectl describe issuer letsencrypt-staging -n apps
ame:         letsencrypt-staging
Namespace:    apps
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Issuer
Metadata:
  Creation Timestamp:  2024-09-09T03:13:54Z
  Generation:          1
  Resource Version:    2957
  UID:                 f5469724-51fd-4f70-9d31-e91f0f45bb52
Spec:
  Acme:
    Email:  email@example.com
    Private Key Secret Ref:
      Name:  letsencrypt-staging
    Server:  https://acme-staging-v02.api.letsencrypt.org/directory
    Solvers:
      http01:
        Ingress:
          Ingress Class Name:  nginx
Status:
  Acme:
    Last Private Key Hash:  zGE6xeUaHb5WXL6CymJK8sHTuLsFYlHPHHM61+IinoQ=
    Last Registered Email:  email@example.com
    Uri:                    https://acme-staging-v02.api.letsencrypt.org/acme/acct/164108913
  Conditions:
    Last Transition Time:  2024-09-09T03:13:56Z
    Message:               The ACME account was registered with the ACME server
    Observed Generation:   1
    Reason:                ACMEAccountRegistered
    Status:                True
    Type:                  Ready
Events:                    <none>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hahoangv.gitbook.io/azure-kubernetes-service/hands-on-provisioning-and-configuring-an-aks-cluster-on-azure-with-pulumi/deploy-ingress-controller-and-configure-ssl-tls/deploy-cert-manager.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
