diff --git a/applications/base/services/external-snapshotter/kustomization.yaml b/applications/base/services/external-snapshotter/kustomization.yaml new file mode 100644 index 0000000..ba59ad6 --- /dev/null +++ b/applications/base/services/external-snapshotter/kustomization.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: external-snapshotter +resources: + [ + "./namespace.yaml", + "github.com/kubernetes-csi/external-snapshotter//client/config/crd?ref=v8.2.1", + "github.com/kubernetes-csi/external-snapshotter//deploy/kubernetes/snapshot-controller?ref=v8.2.1", + ] diff --git a/applications/base/services/external-snapshotter/namespace.yaml b/applications/base/services/external-snapshotter/namespace.yaml new file mode 100644 index 0000000..bf287d6 --- /dev/null +++ b/applications/base/services/external-snapshotter/namespace.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: external-snapshotter diff --git a/applications/base/services/keycloak/00-postgres/postgres-cluster.yaml b/applications/base/services/keycloak/00-postgres/postgres-cluster.yaml index 0275f60..bb8369a 100644 --- a/applications/base/services/keycloak/00-postgres/postgres-cluster.yaml +++ b/applications/base/services/keycloak/00-postgres/postgres-cluster.yaml @@ -4,7 +4,6 @@ metadata: name: postgres-cluster namespace: keycloak spec: - dockerImage: ghcr.io/zalando/spilo-16:3.2-p3 teamId: "acid" numberOfInstances: 3 postgresql: diff --git a/applications/base/services/kube-prometheus-stack/namespace.yaml b/applications/base/services/kube-prometheus-stack/namespace.yaml index d0e0723..09f0d46 100644 --- a/applications/base/services/kube-prometheus-stack/namespace.yaml +++ b/applications/base/services/kube-prometheus-stack/namespace.yaml @@ -3,3 +3,8 @@ apiVersion: v1 kind: Namespace metadata: name: observability + labels: + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/enforce-version: latest + pod-security.kubernetes.io/warn: baseline + pod-security.kubernetes.io/audit: baseline diff --git a/applications/base/services/velero/helm-values/hardened-values-10.1.1.yaml b/applications/base/services/velero/helm-values/hardened-values-10.1.1.yaml index e5a3422..6403147 100644 --- a/applications/base/services/velero/helm-values/hardened-values-10.1.1.yaml +++ b/applications/base/services/velero/helm-values/hardened-values-10.1.1.yaml @@ -5,7 +5,8 @@ # Labels settings in namespace namespace: - labels: {} + labels: + {} # Enforce Pod Security Standards with Namespace Labels # https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/ # pod-security.kubernetes.io/enforce: privileged @@ -34,8 +35,8 @@ image: # One or more secrets to be used when pulling images imagePullSecrets: [] # - registrySecretName -nameOverride: '' -fullnameOverride: '' +nameOverride: "" +fullnameOverride: "" # Annotations to add to the Velero deployment's. Optional. # @@ -53,7 +54,8 @@ labels: {} # # If using kube2iam or kiam, use the following annotation with your AWS_ACCOUNT_ID # and VELERO_ROLE_NAME filled in: -podAnnotations: {} +podAnnotations: + {} # iam.amazonaws.com/role: "arn:aws:iam:::role/" # Additional pod labels for Velero deployment's template. Optional @@ -65,7 +67,8 @@ podLabels: {} # Resource requests/limits to specify for the Velero deployment. # https://velero.io/docs/v1.6/customize-installation/#customize-resource-requests-and-limits -resources: {} +resources: + {} # requests: # cpu: 500m # memory: 128Mi @@ -75,7 +78,8 @@ resources: {} # Container resize policy for the Velero deployment. # See: https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/ -resizePolicy: [] +resizePolicy: + [] # - resourceName: cpu # restartPolicy: NotRequired # - resourceName: memory @@ -83,7 +87,8 @@ resizePolicy: [] # Configure hostAliases for Velero deployment. Optional # For more information, check: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ -hostAliases: [] +hostAliases: + [] # - ip: "127.0.0.1" # hostnames: # - "foo.local" @@ -103,7 +108,8 @@ upgradeCRDsJob: # Extra volumeMounts for the Upgrade CRDs Job. Optional. extraVolumeMounts: [] # Additional values to be used as environment variables. Optional. - extraEnvVars: [] + extraEnvVars: + [] # Simple value # - name: SIMPLE_VAR # value: "simple-value" @@ -135,12 +141,14 @@ initContainers: # SecurityContext to use for the Velero deployment. Optional. # Set fsGroup for `AWS IAM Roles for Service Accounts` # see more informations at: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html -podSecurityContext: {} +podSecurityContext: + {} # fsGroup: 1337 # Container Level Security Context for the 'velero' container of the Velero deployment. Optional. # See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container -containerSecurityContext: {} +containerSecurityContext: + {} # allowPrivilegeEscalation: false # capabilities: # drop: ["ALL"] @@ -151,10 +159,10 @@ containerSecurityContext: {} lifecycle: {} # Pod priority class name to use for the Velero deployment. Optional. -priorityClassName: '' +priorityClassName: "" # Pod runtime class name to use for the Velero deployment. Optional. -runtimeClassName: '' +runtimeClassName: "" # The number of seconds to allow for graceful termination of the pod. Optional. terminationGracePeriodSeconds: 3600 @@ -201,7 +209,8 @@ extraVolumes: [] extraVolumeMounts: [] # Extra K8s manifests to deploy -extraObjects: [] +extraObjects: + [] # - apiVersion: secrets-store.csi.x-k8s.io/v1 # kind: SecretProviderClass # metadata: @@ -241,18 +250,18 @@ metrics: # External/Internal traffic policy setting (Cluster, Local) # https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-policies - externalTrafficPolicy: '' - internalTrafficPolicy: '' + externalTrafficPolicy: "" + internalTrafficPolicy: "" # the IP family policy for the metrics Service to be able to configure dual-stack; see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services). - ipFamilyPolicy: '' + ipFamilyPolicy: "" # a list of IP families for the metrics Service that should be supported, in the order in which they should be applied to ClusterIP. Can be "IPv4" and/or "IPv6". ipFamilies: [] # Pod annotations for Prometheus podAnnotations: - prometheus.io/scrape: 'true' - prometheus.io/port: '8085' + prometheus.io/scrape: "true" + prometheus.io/port: "8085" prometheus.io/path: /metrics serviceMonitor: @@ -333,12 +342,12 @@ metrics: kubectl: image: - repository: docker.io/bitnami/kubectl + repository: docker.io/mikeruu/kubectl # Digest value example: sha256:d238835e151cec91c6a811fe3a89a66d3231d9f64d09e5f3c49552672d271f38. # If used, it will take precedence over the kubectl.image.tag. # digest: # kubectl image tag. If used, it will take precedence over the cluster Kubernetes version. - # tag: 1.16.15 + tag: 1.32.1 # Container Level Security Context for the 'kubectl' container of the crd jobs. Optional. # See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container containerSecurityContext: {} @@ -375,9 +384,9 @@ configuration: # a backup storage location will be created with the name "default". Optional. - name: # provider is the name for the backup storage location provider. - provider: '' + provider: "" # bucket is the name of the bucket to store backups in. Required. - bucket: '' + bucket: "" # caCert defines a base64 encoded CA bundle to use when verifying TLS connections to the provider. Optional. caCert: # prefix is the directory under which all Velero data should be stored within the bucket. Optional. @@ -423,7 +432,7 @@ configuration: # a volume snapshot location will be created with the name "default". Optional. - name: # provider is the name for the volume snapshot provider. - provider: '' + provider: "" credential: # name of the secret used by this volumeSnapshotLocation. name: @@ -561,7 +570,8 @@ configuration: extraArgs: [] # Additional values to be used as environment variables. Optional. - extraEnvVars: [] + extraEnvVars: + [] # Simple value # - name: SIMPLE_VAR # value: "simple-value" @@ -636,7 +646,7 @@ credentials: # Name of a pre-existing secret (if any) in the Velero namespace # that will be used to load environment variables into velero and node-agent. # Secret should be in format - https://kubernetes.io/docs/concepts/configuration/secret/#use-case-as-container-environment-variables - extraSecretRef: '' + extraSecretRef: "" # Whether to create backupstoragelocation crd, if false => do not create a default backup location backupsEnabled: false # Whether to create volumesnapshotlocation crd, if false => disable snapshot feature @@ -649,12 +659,13 @@ nodeAgent: podVolumePath: /var/lib/kubelet/pods pluginVolumePath: /var/lib/kubelet/plugins # Pod priority class name to use for the node-agent daemonset. Optional. - priorityClassName: '' + priorityClassName: "" # Pod runtime class name to use for the node-agent daemonset. Optional. - runtimeClassName: '' + runtimeClassName: "" # Resource requests/limits to specify for the node-agent daemonset deployment. Optional. # https://velero.io/docs/v1.6/customize-installation/#customize-resource-requests-and-limits - resources: {} + resources: + {} # requests: # cpu: 500m # memory: 512Mi @@ -663,7 +674,8 @@ nodeAgent: # memory: 1024Mi # Container resize policy for the node-agent daemonset. # See: https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/ - resizePolicy: [] + resizePolicy: + [] # - resourceName: cpu # restartPolicy: NotRequired # - resourceName: memory @@ -694,7 +706,8 @@ nodeAgent: extraVolumeMounts: [] # Additional values to be used as environment variables for node-agent daemonset. Optional. - extraEnvVars: [] + extraEnvVars: + [] # Simple key/value # - name: SIMPLE_VAR # value: "simple-value" @@ -715,7 +728,8 @@ nodeAgent: # Configure hostAliases for node-agent daemonset. Optional # For more information, check: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ - hostAliases: [] + hostAliases: + [] # - ip: "127.0.0.1" # hostnames: # - "foo.local" diff --git a/applications/base/services/velero/namespace.yaml b/applications/base/services/velero/namespace.yaml index 7dd5bd7..e5e0048 100644 --- a/applications/base/services/velero/namespace.yaml +++ b/applications/base/services/velero/namespace.yaml @@ -3,3 +3,6 @@ apiVersion: v1 kind: Namespace metadata: name: velero + labels: + pod-security.kubernetes.io/audit: baseline + pod-security.kubernetes.io/warn: baseline diff --git a/docs/adding-new-service.md b/docs/adding-new-service.md new file mode 100644 index 0000000..9e98ad2 --- /dev/null +++ b/docs/adding-new-service.md @@ -0,0 +1,460 @@ +# Adding a New Service to openCenter GitOps + +This guide explains how to add a new service to the openCenter GitOps base repository using the standardized Flux CD patterns. We'll use **cert-manager** as a reference example to illustrate the complete process. + +## Overview + +All services in openCenter GitOps follow a consistent structure using Flux CD's GitOps approach with: +- **HelmRepository**: Defines the Helm chart source +- **HelmRelease**: Manages the application deployment +- **Kustomization**: Orchestrates resources and generates secrets +- **Namespace**: Isolates the service resources +- **Hardened Values**: Security-focused Helm configurations + +## Service Directory Structure + +Each service follows this standardized directory layout: + +``` +applications/base/services/my-service/ +├── kustomization.yaml # Main orchestration file +├── namespace.yaml # Service namespace +├── source.yaml # HelmRepository definition +├── helmrelease.yaml # HelmRelease configuration +└── helm-values/ + └── hardened-values-vX.Y.Z.yaml # Security-hardened Helm values +``` + +## Step-by-Step Implementation Guide + +### Step 1: Create the Service Directory Structure + +Create the directory structure for your new service: + +```bash +mkdir -p applications/base/services/my-service/helm-values +``` + +### Step 2: Create the Namespace Resource + +Create `applications/base/services/my-service/namespace.yaml`: + +```yaml +--- +apiVersion: v1 +kind: Namespace +metadata: + name: my-service +``` + +**Key Points:** +- Use a clear, descriptive namespace name +- Follow kebab-case naming convention +- Keep namespace name consistent with service name + +### Step 3: Define the Helm Repository Source + +Create `applications/base/services/my-service/source.yaml`: + +```yaml +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: my-service-repo +spec: + url: https://charts.example.com + interval: 1h +``` + +**Example using cert-manager:** +```yaml +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: jetstack +spec: + url: https://charts.jetstack.io + interval: 1h +``` + +**Key Configuration:** +- `metadata.name`: Unique identifier for the repository +- `spec.url`: HTTPS URL to the Helm repository +- `spec.interval`: How often to check for updates (typically 1h) + +### Step 4: Create the HelmRelease Configuration + +Create `applications/base/services/my-service/helmrelease.yaml`: + +```yaml +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: my-service + namespace: my-service +spec: + releaseName: my-service + interval: 5m + timeout: 10m + driftDetection: + mode: enabled + install: + remediation: + retries: 3 + remediateLastFailure: true + upgrade: + remediation: + retries: 0 + remediateLastFailure: false + targetNamespace: my-service + chart: + spec: + chart: my-service-chart + version: vX.Y.Z + sourceRef: + kind: HelmRepository + name: my-service-repo + namespace: my-service + valuesFrom: + - kind: Secret + name: my-service-values-base + valuesKey: hardened.yaml + - kind: Secret + name: my-service-values-override + valuesKey: override.yaml + optional: true +``` + +**Example using cert-manager:** +```yaml +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: cert-manager + namespace: cert-manager +spec: + releaseName: cert-manager + interval: 5m + timeout: 10m + driftDetection: + mode: enabled + install: + remediation: + retries: 3 + remediateLastFailure: true + upgrade: + remediation: + retries: 0 + remediateLastFailure: false + targetNamespace: cert-manager + chart: + spec: + chart: cert-manager + version: v1.18.2 + sourceRef: + kind: HelmRepository + name: jetstack + namespace: cert-manager + valuesFrom: + - kind: Secret + name: cert-manager-values-base + valuesKey: hardened.yaml + - kind: Secret + name: cert-manager-values-override + valuesKey: override.yaml + optional: true +``` + +**Key Configuration:** +- `spec.interval`: 5m reconciliation cycle (standard) +- `spec.timeout`: 10m installation timeout (standard) +- `spec.driftDetection.mode`: enabled (required for consistency) +- `spec.install.remediation.retries`: 3 (standard retry policy) +- `valuesFrom`: References to hardened values and optional overrides + +### Step 5: Create Hardened Helm Values + +Create `applications/base/services/my-service/helm-values/hardened-values-vX.Y.Z.yaml`: + +This file contains security-hardened configuration for the Helm chart. Use the chart version in the filename for versioning. + +**Example structure for cert-manager:** +```yaml +# Security configurations +replicaCount: 2 +securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault +containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + +# Production configurations +prometheus: + enabled: true +config: + enableGatewayAPI: true +nodeSelector: + kubernetes.io/os: linux + +# Feature enablement +crds: + enabled: true + keep: true +``` + +**Security Hardening Guidelines:** +- Enable non-root execution (`runAsNonRoot: true`) +- Use security profiles (`seccompProfile.type: RuntimeDefault`) +- Drop all capabilities (`capabilities.drop: [ALL]`) +- Use read-only root filesystem (`readOnlyRootFilesystem: true`) +- Disable privilege escalation (`allowPrivilegeEscalation: false`) +- Enable monitoring (`prometheus.enabled: true`) +- Use Linux node selectors for mixed OS clusters + +### Step 6: Create the Kustomization File + +Create `applications/base/services/my-service/kustomization.yaml`: + +```yaml +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: [./namespace.yaml, ./source.yaml, ./helmrelease.yaml] + +secretGenerator: + - name: my-service-values-base + type: Opaque + files: [hardened.yaml=helm-values/hardened-values-vX.Y.Z.yaml] + options: + disableNameSuffixHash: true +``` + +**Example using cert-manager:** +```yaml +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: [./namespace.yaml, ./source.yaml, ./helmrelease.yaml] + +secretGenerator: + - name: cert-manager-values-base + type: Opaque + files: [hardened.yaml=helm-values/hardened-values-v1.18.2.yaml] + options: + disableNameSuffixHash: true +``` + +**Key Configuration:** +- `resources`: List all YAML files to include +- `secretGenerator`: Creates Kubernetes secrets from hardened values +- `disableNameSuffixHash: true`: Required for consistent secret naming + +### Step 7: Integration with Parent Kustomization + +To include your new service in the GitOps deployment, it must be referenced in a parent kustomization file. Services are typically included at the cluster or environment level. + +For example, in `applications/overlays/my-cluster/kustomization.yaml`: + +```yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../../base/services/cert-manager + - ../../base/services/my-service # Add your new service here +``` + +## Validation and Testing + +### Step 1: Validate Kustomization + +Test the kustomization builds correctly: + +```bash +cd applications/base/services/my-service +kubectl kustomize . --dry-run=server +``` + +### Step 2: Validate HelmRelease + +Check if the HelmRelease configuration is valid: + +```bash +kubectl apply --dry-run=server -f helmrelease.yaml +``` + +### Step 3: Deploy and Monitor + +After committing to Git, monitor the deployment: + +```bash +# Check Flux reconciliation +kubectl get helmreleases -n my-service + +# Check application status +kubectl get pods -n my-service + +# View Flux logs if issues occur +kubectl logs -n flux-system deploy/helm-controller +``` + +## Common Configuration Patterns + +### Multiple Helm Values Files + +For complex services requiring multiple configuration files: + +```yaml +# In kustomization.yaml +secretGenerator: + - name: my-service-values-base + type: Opaque + files: + - hardened.yaml=helm-values/hardened-values-v1.0.0.yaml + - monitoring.yaml=helm-values/monitoring-overrides.yaml + - networking.yaml=helm-values/networking-overrides.yaml + options: + disableNameSuffixHash: true +``` + +```yaml +# In helmrelease.yaml +valuesFrom: + - kind: Secret + name: my-service-values-base + valuesKey: hardened.yaml + - kind: Secret + name: my-service-values-base + valuesKey: monitoring.yaml + - kind: Secret + name: my-service-values-base + valuesKey: networking.yaml +``` + +### Services with Custom Resources + +For services that deploy CRDs or require multiple namespaces: + +```yaml +# In kustomization.yaml +resources: + - ./namespace.yaml + - ./source.yaml + - ./helmrelease.yaml + - ./custom-resources/ +``` + +### Version Pinning Strategy + +Always pin specific versions in HelmReleases: + +```yaml +chart: + spec: + chart: my-service + version: v1.2.3 # Exact version, not ranges +``` + +## Troubleshooting Guide + +### Common Issues + +1. **HelmRelease Stuck in Installing State** + ```bash + kubectl describe helmrelease my-service -n my-service + kubectl logs -n flux-system deploy/helm-controller + ``` + +2. **Secret Generation Failures** + ```bash + kubectl kustomize applications/base/services/my-service + ``` + +3. **Chart Source Not Found** + ```bash + kubectl get helmrepositories -A + kubectl describe helmrepository my-service-repo -n my-service + ``` + +4. **Values Override Issues** + ```bash + kubectl get secret my-service-values-base -n my-service -o yaml + ``` + +### Debugging Commands + +```bash +# Force reconciliation +flux reconcile helmrelease my-service -n my-service + +# Check all Flux resources +kubectl get gitrepositories,helmrepositories,helmreleases -A + +# View generated manifests +helm template my-service-repo/my-service --values /tmp/values.yaml +``` + +## Best Practices + +### Security +- Always use hardened values with security contexts +- Pin exact chart versions, avoid ranges or latest +- Enable drift detection for configuration consistency +- Use least-privilege RBAC configurations + +### Reliability +- Set appropriate timeouts and retry policies +- Use health checks and readiness probes +- Configure resource limits and requests +- Enable monitoring and observability + +### Maintainability +- Use consistent naming conventions +- Version hardened values files with chart versions +- Document service-specific configurations +- Follow the established directory structure + +### GitOps Workflow +- Commit all changes to version control +- Use pull requests for service additions +- Test in development environments first +- Monitor deployments after changes + +## Example: Complete cert-manager Implementation + +Here's the complete cert-manager implementation as a reference: + +**Directory Structure:** +``` +applications/base/services/cert-manager/ +├── kustomization.yaml +├── namespace.yaml +├── source.yaml +├── helmrelease.yaml +└── helm-values/ + └── hardened-values-v1.18.2.yaml +``` + +**File Contents:** + +See the actual files in `applications/base/services/cert-manager/` for the complete, production-ready implementation that follows all the patterns described in this guide. + +## Next Steps + +After successfully adding your service: + +1. **Monitor Deployment**: Watch the HelmRelease status and pod health +2. **Configure Monitoring**: Ensure Prometheus scraping and Grafana dashboards +3. **Test Functionality**: Verify the service works as expected +4. **Document Usage**: Add service-specific documentation +5. **Set Up Alerts**: Configure alerting rules for service health + +This standardized approach ensures consistency, security, and maintainability across all services in the openCenter GitOps platform. \ No newline at end of file diff --git a/iac/cloud/openstack/lib/openstack-keypair/main.tf b/iac/cloud/openstack/lib/openstack-keypair/main.tf index 37808dc..b24027f 100644 --- a/iac/cloud/openstack/lib/openstack-keypair/main.tf +++ b/iac/cloud/openstack/lib/openstack-keypair/main.tf @@ -1,5 +1,5 @@ resource "openstack_compute_keypair_v2" "ssh_keypair" { - name = format("%skey", var.naming_prefix) + name = replace(format("%skey", var.naming_prefix), ".", "-") } resource "local_file" "private_key" { @@ -12,4 +12,4 @@ resource "local_file" "public_key" { content = openstack_compute_keypair_v2.ssh_keypair.public_key filename = "${path.root}/id_rsa.pub" file_permission = "0644" -} \ No newline at end of file +} diff --git a/iac/cni/calico/main.tf b/iac/cni/calico/main.tf index ec5c728..1b69003 100644 --- a/iac/cni/calico/main.tf +++ b/iac/cni/calico/main.tf @@ -15,5 +15,6 @@ resource "local_file" "calico_values" { }) filename = "${path.root}/../../../applications/overlays/${var.cluster_name}/services/calico/helm-values/override_values.yaml" + file_permission = 0644 } \ No newline at end of file diff --git a/iac/provider/kubespray/main.tf b/iac/provider/kubespray/main.tf index 9eec509..0c47839 100644 --- a/iac/provider/kubespray/main.tf +++ b/iac/provider/kubespray/main.tf @@ -23,6 +23,7 @@ resource "local_file" "ansible_inventory" { }) filename = "./inventory/inventory.yaml" + file_permission = 0644 depends_on = [var.master_nodes, var.worker_nodes] # lifecycle { # replace_triggered_by = [var.master_nodes, var.worker_nodes] @@ -53,6 +54,7 @@ resource "local_file" "k8s_cluster" { }) filename = "./inventory/group_vars/k8s_cluster/k8s-cluster.yml" + file_permission = 0644 depends_on = [local_file.ansible_inventory] } @@ -69,6 +71,7 @@ resource "local_file" "addons" { }) filename = "./inventory/group_vars/k8s_cluster/addons.yml" + file_permission = 0644 depends_on = [local_file.ansible_inventory] } @@ -89,6 +92,7 @@ resource "local_file" "k8s_hardening" { }) filename = "./inventory/k8s_hardening.yml" + file_permission = 0644 depends_on = [local_file.ansible_inventory] } @@ -210,6 +214,7 @@ resource "local_file" "os_hardening_playbook" { content = templatefile("${path.module}/templates/os_hardening_playbook.tpl", {}) + file_permission = 0644 filename = "./inventory/os_hardening_playbook.yml" }