This document outlines the security practices, Identity and Access Management (IAM) approach followed by this project.
This project follows the principle of least privilege, using Role-Based Access Control (RBAC) for both Azure and Kubernetes.
For Azure resources, we use Azure RBAC to define access levels for service principals, users, and groups.
kubectl api-resources | grep rbac
Output confirms presence of:
roles
rolebindings
clusterroles
clusterrolebindings
This ensures fine-grained access control is in place for users and service accounts in the cluster.
RBAC role assigned to the Nginx Ingress Controller in the expensy namespace:
kubectl get role my-nginx-ingress-controller-ingress-nginx -n expensy -o yaml
This role allows specific operations required by the ingress controller, scoped only to the namespace it manages. Fine-grained permission control ensures least privilege.
Sensitive information, such as API keys, credentials, and tokens, is stored securely in:
- GitHub Secrets: We store environment-specific secrets like Azure credentials, DockerHub tokens in GitHub Secrets to ensure they are kept safe.
- Kubernetes Secrets: For storing and managing kubernetes related secrets such as database connection strings, database URL.
β To securely configure the secrets in GitHub follow these steps:
- Go to your forked repository on GitHub.
- Navigate to Settings β Secrets and variables β Actions.
- Click New repository secret.
- Add the following secrets as listed below.
| Secret Name | Description | Required |
|---|---|---|
AKS_CLUSTER_NAME |
Name of your Azure Kubernetes Service (AKS) cluster | β |
AKS_RESOURCE_GROUP |
Resource group where your AKS cluster is deployed | β |
AZURE_CREDENTIALS |
JSON string with Azure Service Principal credentials for deployment | β |
DOCKERHUB_USERNAME |
Your Docker Hub username | β |
DOCKERHUB_TOKEN |
Docker Hub access token or password | β |
NEXT_PUBLIC_API_URL |
Public API base URL for the backend | β |
{
"clientId": "<your-client-id>",
"clientSecret": "<your-client-secret>",
"subscriptionId": "<your-subscription-id>",
"tenantId": "<your-tenant-id>",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}```
kubectl create secret generic expensy-secrets \
--from-literal=KEY_NAME="redis" \
--from-literal=KEY_NAME="redis-password" \
--from-literal=KEY_NAME="mongodb" \
--from-literal=KEY_NAME="mongodb-password" \
--from-literal=KEY_NAME="database-URL" \
--from-literal=KEY_NAME="database-URL-link" \
-n expensy
```
Then in your microservice Deployment manifests, you can reference them like:
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: expensy-secrets
key: redis-password
Environment variables are used for configuration, and secret values are never hardcoded in the code. They are injected into the environment during runtime or through CI/CD pipelines.
All secrets stored in GitHub Actions and Kubernetes secrets are encrypted at rest and are only accessible by authorized users or services. For GitHub Actions secrets, only GitHub Actions workflows have access, based on defined permissions. Secrets in Azure are encrypted using Azure's managed encryption services.
All external-facing traffic to this application is secured using TLS. The application runs behind an NGINX Ingress Controller in a Kubernetes cluster, with HTTPS enforced via Ingress TLS settings.
- TLS certificates are issued via Certbot and automatically renewed using a cron job.
- Certificates are stored securely in the cluster as Kubernetes Secrets.
- The Ingress ensures all traffic is redirected to HTTPS, preventing unencrypted access.