commit 98d32642cddce71efc30bf743c2e1baed7e7bc7f Author: noussair.hamrit Date: Mon Jun 16 16:29:39 2025 +0200 Initial commit - update else condition on the line 239 in templates/Deployment - update st-common version from 0.1.10 to 0.1.12 on Chart.yaml file - add gitlab ci/cd pipeline to package the Helm chart into a .tgz. and Publish it to GitLab’s Helm package registry diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..ee96660 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,40 @@ +default: + tags: + - docker-test + +stages: + - package + - publish + +variables: + CHART_NAME: "freeradius" + CHART_VERSION: "1.0.3" + PACKAGE_PATH: "packages" + HELM_EXPERIMENTAL_OCI: "1" + +package_chart: + stage: package + image: + name: alpine/helm:3.14.0 + entrypoint: [""] + script: + - helm repo add startechnica https://startechnica.github.io/apps + - helm dependency build . + - mkdir -p $PACKAGE_PATH + - helm package . --destination $PACKAGE_PATH + artifacts: + paths: + - ${PACKAGE_PATH}/${CHART_NAME}-${CHART_VERSION}.tgz + + +publish_chart: + stage: publish + image: alpine/curl:8.14.1 + script: + - | + curl --fail-with-body --request POST \ + --user gitlab-ci-token:$CI_JOB_TOKEN \ + --form "chart=@${PACKAGE_PATH}/${CHART_NAME}-${CHART_VERSION}.tgz" \ + "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/api/stable/charts" + only: + - main \ No newline at end of file diff --git a/Chart.lock b/Chart.lock new file mode 100644 index 0000000..57da691 --- /dev/null +++ b/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: st-common + repository: https://startechnica.github.io/apps + version: 0.1.12 +- name: mariadb + repository: oci://registry-1.docker.io/bitnamicharts + version: 20.5.9 +digest: sha256:03a311ace58596d28267595eab6c85c5d39af13a5864dbe04be8931a2262b6c7 +generated: "2025-06-16T16:20:04.252816273+02:00" diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 0000000..50572a4 --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,34 @@ +annotations: + category: AccessManagement +apiVersion: v2 +appVersion: 3.2.7 +dependencies: +- name: st-common + repository: https://startechnica.github.io/apps + version: 0.1.12 +- condition: mariadb.enabled + name: mariadb + repository: oci://registry-1.docker.io/bitnamicharts + version: 20.x.x +description: FreeRADIUS is a modular, high performance free RADIUS suite developed + and distributed under the GNU General Public License, version 2, and is free for + download and use. +home: https://github.com/startechnica/apps/tree/main/charts/freeradius +icon: https://freeradius.org/img/wordmark.svg +keywords: +- freeradius +- radius +- mysql +- postgresql +- ldap +kubeVersion: '>=1.24.0-0' +maintainers: +- email: firmansyah@nainggolan.id + name: firmansyahn + url: https://firmansyah.nainggolan.id +name: freeradius +sources: +- https://freeradius.org/ +- https://github.com/FreeRADIUS/freeradius-server +type: application +version: 1.0.3 diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bcf2ae --- /dev/null +++ b/README.md @@ -0,0 +1,325 @@ + + +# Helm chart for FreeRADIUS + +FreeRADIUS is a modular, high performance free RADIUS suite developed and distributed under the GNU General Public License, version 2, and is free for download and use. + +[Overview of FreeRADIUS](https://freeradius.org/) + +**This chart is not maintained by the upstream project and any issues with the chart should be raised [here](https://github.com/startechnica/apps/issues/new/choose)** + +## TL;DR + +```console +helm repo add startechnica https://startechnica.github.io/apps +helm install my-release startechnica/freeradius +``` + +## Prerequisites + +- Kubernetes 1.22+ +- Helm 3.10.0+ + +## Installing the Chart + +To install the chart with the release name `my-release` on `my-release` namespace: + +```console +helm repo add startechnica https://startechnica.github.io/apps +helm install my-release startechnica/freeradius --namespace my-release --create-namespace +``` + +These commands deploy FreeRADIUS on the Kubernetes cluster in the default configuration. + +> **Tip**: List all releases using `helm list -A` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +helm delete my-release --namespace my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Parameters + +### Global parameters + +| Name | Description | Value | +| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----- | +| `global.imageRegistry` | Global Docker image registry | `""` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | +| `global.namespaceOverride` | Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride | `""` | + + +### Common parameters + +| Name | Description | Value | +| -------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------- | +| `kubeVersion` | Force target Kubernetes version (using Helm capabilities if not set) | `""` | +| `nameOverride` | String to partially override common.names.fullname template with a string (will prepend the release name) | `""` | +| `namespaceOverride` | String to fully override common.names.namespace | `""` | +| `fullnameOverride` | String to fully override common.names.fullname template with a string | `""` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `schedulerName` | Name of the Kubernetes scheduler (other than default) | `""` | +| `clusterDomain` | Kubernetes DNS Domain name to use | `cluster.local` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template) | `[]` | +| `diagnosticMode.enabled` | Enable diagnostic mode (all probes will be disabled and the command will be overridden) | `false` | +| `diagnosticMode.command` | Command to override all containers in the deployment | `[]` | +| `diagnosticMode.args` | Args to override all containers in the deployment | `[]` | + + +### FreeRADIUS parameters + +| Name | Description | Value | +| ----------------------------------------------| -------------------------------------------------------------------------------------------------------------------------| -------------------------------| +| `image.registry` | FreeRADIUS image registry | `docker.io` | +| `image.repository` | FreeRADIUS image repository | `freeradius/freeradius-server` | +| `image.tag` | FreeRADIUS image tag (immutable tags are recommended) | `3.2.3` | +| `image.pullPolicy` | FreeRADIUS image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify docker-registry secret names as an array | `[]` | +| `image.debug` | Set to true if you would like to see extra information on logs | `false` | +| `hostAliases` | Deployment pod host aliases | `[]` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `args` | Override default container args (useful when using custom images) | `[]` | +| `extraEnvVars` | Extra environment variables to be set on FreeRADIUS containers | `[]` | +| `extraEnvVarsCM` | ConfigMap with extra environment variables | `""` | +| `extraEnvVarsSecret` | Secret with extra environment variables | `""` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.clusterIP` | Specific cluster IP when service type is cluster IP. Use `None` for headless service | `""` | +| `service.ports.auth` | FreeRADIUS Authentication and Authorization service port | `1812` | +| `service.ports.acct` | FreeRADIUS Accounting service port | `1813` | +| `service.ports.coa` | FreeRADIUS CoA service port | `3799` | +| `service.ports.radsec` | FreeRADIUS RadSec service port | `2083` | +| `service.ports.status` | FreeRADIUS Status service port | `18121` | +| `service.nodePorts.auth` | Specify the nodePort value for the LoadBalancer and NodePort for Authentication service types. | `""` | +| `service.nodePorts.acct` | Specify the nodePort value for the LoadBalancer and NodePort for Accounting service types. | `""` | +| `service.nodePorts.coa` | Specify the nodePort value for the LoadBalancer and NodePort for CoA service types. | `""` | +| `service.nodePorts.radsec` | Specify the nodePort value for the LoadBalancer and NodePort for RadSec service types. | `""` | +| `service.nodePorts.status` | Specify the nodePort value for the LoadBalancer and NodePort for Status service types. | `""` | +| `service.extraPorts` | Extra ports to expose (normally used with the `sidecar` value) | `[]` | +| `service.externalIPs` | External IP list to use with ClusterIP service type | `[]` | +| `service.loadBalancerIP` | `loadBalancerIP` if service type is `LoadBalancer` | `""` | +| `service.loadBalancerSourceRanges` | Addresses that are allowed when svc is `LoadBalancer` | `[]` | +| `service.externalTrafficPolicy` | FreeRADIUS service external traffic policy | `Cluster` | +| `service.annotations` | Additional annotations for FreeRADIUS service | `{}` | +| `service.sessionAffinity` | Session Affinity for Kubernetes service, can be `None` or `ClientIP` | `None` | +| `service.sessionAffinityConfig` | Additional settings for the sessionAffinity | `{}` | +| `serviceAccount.create` | Specify whether a ServiceAccount should be created | `false` | +| `serviceAccount.name` | Name of the service account to use. If not set and create is true, a name is generated using the fullname template. | `""` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token for the server service account | `false` | +| `serviceAccount.annotations` | Annotations for service account. Evaluated as a template. Only used if `create` is `true`. | `{}` | +| `command` | Override default container command (useful when using custom images) | `[]` | +| `extraEnvVars` | Array containing extra env vars to configure FreeRADIUS | `[]` | +| `extraEnvVarsCM` | ConfigMap containing extra env vars to configure FreeRADIUS | `""` | +| `extraEnvVarsSecret` | Secret containing extra env vars to configure FreeRADIUS | `""` | +| `rbac.create` | Specify whether RBAC resources should be created and used | `false` | +| `podSecurityContext.enabled` | Enable security context | `true` | +| `podSecurityContext.fsGroup` | Group ID for the container filesystem | `101` | +| `podSecurityContext.runAsUser` | User ID for the container | `101` | +| `containerSecurityContext.enabled` | Enabled FreeRADIUS container Security Context | `true` | +| `containerSecurityContext.runAsUser` | Set FreeRADIUS container Security Context runAsUser | `101` | +| `containerSecurityContext.runAsNonRoot` | Set FreeRADIUS container Security Context runAsNonRoot | `true` | +| `tls.enabled` | Enable TLS support for replication traffic | `false` | +| `tls.autoGenerated` | Generate automatically self-signed TLS certificates | `false` | +| `tls.autoGenerator.certmanager.enabled` | | `false` | +| `tls.certificatesSecret` | Name of the secret that contains the certificates | `"false"` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename | `""` | +| `configuration` | Configuration for the FreeRADIUS server (`radiusd.conf`) | `""` | +| `configurationConfigMap` | ConfigMap with the FreeRADIUS configuration files (Note: Overrides `configuration`). The value is evaluated as a template. | `""` | +| `initdbScripts` | Specify dictionary of scripts to be run at first boot | `{}` | +| `initdbScriptsConfigMap` | ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`) | `""` | +| `extraFlags` | FreeRADIUS additional command line flags | `""` | +| `replicaCount` | Desired number of cluster nodes | `3` | +| `podLabels` | Extra labels for FreeRADIUS pods | `{}` | +| `podAnnotations` | Annotations for FreeRADIUS pods | `{}` | +| `podAffinityPreset` | Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `podAntiAffinityPreset` | Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `nodeAffinityPreset.type` | Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `nodeAffinityPreset.key` | Node label key to match. Ignored if `affinity` is set. | `""` | +| `nodeAffinityPreset.values` | Node label values to match. Ignored if `affinity` is set. | `[]` | +| `affinity` | Affinity for pod assignment | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Tolerations for pod assignment | `[]` | +| `topologySpreadConstraints` | Topology Spread Constraints for pods assignment | `[]` | +| `lifecycleHooks` | for the galera container(s) to automate configuration before or after startup | `{}` | +| `containerPorts.auth` | Auth database container port | `1812` | +| `containerPorts.acct` | Acct cluster container port | `1813` | +| `containerPorts.coa` | CoA container port | `3799` | +| `containerPorts.radsec` | RadSec container port | `2083` | +| `containerPorts.status` | Status container port | `18121` | +| `persistence.enabled` | Enable persistence using PVC | `true` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim` | `""` | +| `persistence.subPath` | Subdirectory of the volume to mount | `""` | +| `persistence.mountPath` | Path to mount the volume at | `/startechnica/freeradius` | +| `persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `persistence.storageClass` | Persistent Volume Storage Class | `""` | +| `persistence.annotations` | Persistent Volume Claim annotations | `{}` | +| `persistence.labels` | Persistent Volume Claim Labels | `{}` | +| `persistence.accessModes` | Persistent Volume Access Modes | `["ReadWriteOnce"]` | +| `persistence.size` | Persistent Volume Size | `8Gi` | +| `priorityClassName` | Priority Class Name for Statefulset | `""` | +| `initContainers` | Additional init containers (this value is evaluated as a template) | `[]` | +| `sidecars` | Add additional sidecar containers (this value is evaluated as a template) | `[]` | +| `extraVolumes` | Extra volumes | `[]` | +| `extraVolumeMounts` | Mount extra volume(s) | `[]` | +| `resources.limits` | The resources limits for the container | `{}` | +| `resources.requests` | The requested resources for the container | `{}` | +| `livenessProbe.enabled` | Turn on and off liveness probe | `true` | +| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | `120` | +| `livenessProbe.periodSeconds` | How often to perform the probe | `10` | +| `livenessProbe.timeoutSeconds` | When the probe times out | `1` | +| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe | `3` | +| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe | `1` | +| `readinessProbe.enabled` | Turn on and off readiness probe | `true` | +| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | `30` | +| `readinessProbe.periodSeconds` | How often to perform the probe | `10` | +| `readinessProbe.timeoutSeconds` | When the probe times out | `1` | +| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe | `3` | +| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe | `1` | +| `startupProbe.enabled` | Turn on and off startup probe | `false` | +| `startupProbe.initialDelaySeconds` | Delay before startup probe is initiated | `120` | +| `startupProbe.periodSeconds` | How often to perform the probe | `10` | +| `startupProbe.timeoutSeconds` | When the probe times out | `1` | +| `startupProbe.failureThreshold` | Minimum consecutive failures for the probe | `48` | +| `startupProbe.successThreshold` | Minimum consecutive successes for the probe | `1` | +| `customStartupProbe` | Custom liveness probe for the Web component | `{}` | +| `customLivenessProbe` | Custom liveness probe for the Web component | `{}` | +| `customReadinessProbe` | Custom rediness probe for the Web component | `{}` | +| `podDisruptionBudget.create` | Specifies whether a Pod disruption budget should be created | `false` | +| `podDisruptionBudget.minAvailable` | Minimum number / percentage of pods that should remain scheduled | `1` | +| `podDisruptionBudget.maxUnavailable` | Maximum number / percentage of pods that may be made unavailable | `""` | +| `metrics.enabled` | Start a side-car prometheus exporter | `false` | +| `metrics.image.registry` | FreeRADIUS Prometheus exporter image registry | `""` | +| `metrics.image.repository` | FreeRADIUS Prometheus exporter image repository | `""` | +| `metrics.image.tag` | FreeRADIUS Prometheus exporter image tag (immutable tags are recommended) | `""` | +| `metrics.image.pullPolicy` | FreeRADIUS Prometheus exporter image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | FreeRADIUS Prometheus exporter image pull secrets | `[]` | +| `metrics.extraFlags` | FreeRADIUS Prometheus exporter additional command line flags | `[]` | +| `metrics.resources.limits` | The resources limits for the container | `{}` | +| `metrics.resources.requests` | The requested resources for the container | `{}` | +| `metrics.service.type` | Prometheus exporter service type | `ClusterIP` | +| `metrics.service.port` | Prometheus exporter service port | `9104` | +| `metrics.service.annotations` | Prometheus exporter service annotations | `{}` | +| `metrics.service.loadBalancerIP` | Load Balancer IP if the Prometheus metrics server type is `LoadBalancer` | `""` | +| `metrics.service.clusterIP` | Prometheus metrics service Cluster IP | `""` | +| `metrics.service.loadBalancerSourceRanges` | Prometheus metrics service Load Balancer sources | `[]` | +| `metrics.service.externalTrafficPolicy` | Prometheus metrics service external traffic policy | `Cluster` | +| `metrics.serviceMonitor.enabled` | if `true`, creates a Prometheus Operator ServiceMonitor (also requires `metrics.enabled` to be `true`) | `false` | +| `metrics.serviceMonitor.namespace` | Optional namespace which Prometheus is running in | `""` | +| `metrics.serviceMonitor.jobLabel` | The name of the label on the target service to use as the job name in prometheus. | `""` | +| `metrics.serviceMonitor.interval` | How frequently to scrape metrics (use by default, falling back to Prometheus' default) | `""` | +| `metrics.serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `""` | +| `metrics.serviceMonitor.selector` | ServiceMonitor selector labels | `{}` | +| `metrics.serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping | `[]` | +| `metrics.serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion | `[]` | +| `metrics.serviceMonitor.honorLabels` | honorLabels chooses the metric's labels on collisions with target labels | `false` | +| `metrics.serviceMonitor.labels` | ServiceMonitor extra labels | `{}` | +| `metrics.prometheusRules.enabled` | if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true`, and makes little sense without ServiceMonitor) | `false` | +| `metrics.prometheusRules.additionalLabels` | Additional labels to add to the PrometheusRule so it is picked up by the operator | `{}` | +| `metrics.prometheusRules.rules` | PrometheusRule rules to configure | `{}` | + + +### Custom FreeRADIUS enabled mods parameters + +| Name | Description | Value | +| ------------------------------------------ | --------------------------------------------------- | ----------------- | +| `modsEnabled.sql.enabled` | Enable FreeRADIUS SQL module | `false` | +| `modsEnabled.sql.dialect` | The driver module used to execute the queries. | `mysql` | +| `modsEnabled.sql.table.acct1` | Tables containing 'accounting' items | `radacct` | +| `modsEnabled.sql.table.acct2` | Tables containing 'accounting' items | `radacct` | +| `modsEnabled.sql.table.authcheck` | Tables containing 'check' items | `radcheck` | +| `modsEnabled.sql.table.authreply` | Tables containing 'reply' items | `radreply` | +| `modsEnabled.sql.table.client` | Table to keep radius client info | `nas` | +| `modsEnabled.sql.table.groupcheck` | Tables containing 'check' items | `radgroupcheck` | +| `modsEnabled.sql.table.groupreply` | Tables containing 'reply' items | `radgroupreply` | +| `modsEnabled.sql.table.postauth` | Allow for storing data after authentication | `radpostauth` | +| `modsEnabled.sql.table.usergroup` | Table to keep group info | `radusergroup` | +| `modsEnabled.sql.tls.enabled` | Enable FreeRADIUS SQL TLS module | `false` | +| `modsEnabled.sql.tls.autoGenerated` | | `false` | +| `modsEnabled.sql.tls.certificatesSecret` | | `""` | +| `modsEnabled.sql.tls.certFilename` | | `""` | +| `modsEnabled.sql.tls.certKeyFilename` | | `""` | +| `modsEnabled.sql.tls.certCAFilename` | | `""` | +| `modsEnabled.sql.tls.existingTlsSecret` | | `""` | +| `modsEnabled.sql.tls.privateKeyPassword` | | `""` | + + +### Custom FreeRADIUS enabled sites parameters + +| Name | Description | Value | +| ------------------------------------------ | ------------------------------------------------------------------------------- | ----------------- | +| `sitesEnabled.coa.enabled` | Enable FreeRADIUS coa service | `false` | +| `sitesEnabled.status.enabled` | Enable FreeRADIUS status service | `true` | +| `sitesEnabled.tls.enabled` | Enable FreeRADIUS radsec service | `false` | +| `sitesEnabled.tls.cipher` | | `false` | +| `sitesEnabled.tls.privateKeyPassword` | | `false` | + + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install my-release \ + --set imagePullPolicy=Always \ + startechnica/freeradius +``` + +The above command sets the `imagePullPolicy` to `Always`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +helm install my-release startechnica/freeradius -f values.yaml +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +### Adding extra environment variables + +In case you want to add extra environment variables (useful for advanced operations like custom init scripts), you can use the `extraEnvVars` property. + +```yaml +extraEnvVars: + - name: LOG_LEVEL + value: error +``` + +Alternatively, you can use a ConfigMap or a Secret with the environment variables. To do so, use the `extraEnvVarsCM` or the `extraEnvVarsSecret` values. + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `affinity` parameter. Find more information about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +### Deploying extra resources + +There are cases where you may want to deploy extra objects, such a ConfigMap containing your app's configuration or some extra deployment with a micro service used by your app. For covering this case, the chart allows adding the full specification of other objects using the `extraDeploy` parameter. + +## Troubleshooting + +Find more information about how to deal with common errors related to Startechnica's Helm charts in [this troubleshooting guide](https://startechnica.github.io/doc/troubleshoot-helm-chart-issues). + +## Upgrading + +## License + +Copyright © 2023 Startechnica + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/archive/coa-master b/archive/coa-master new file mode 100644 index 0000000..039e3d8 --- /dev/null +++ b/archive/coa-master @@ -0,0 +1,55 @@ +# -*- text -*- +###################################################################### +# +# Sample virtual server for receiving a CoA or Disconnect-Request packet. +# +server coa { + namespace = $ENV{FREERADIUS_SITES_NAMESPACE} + + # Listen on the CoA port. + # + # This uses the normal set of clients, with the same secret as for + # authentication and accounting. + # + listen { + type = CoA-Request + type = Disconnect-Request + + transport = udp + + udp { + ipaddr = $ENV{FREERADIUS_SITES_COA_LISTEN} + port = $ENV{FREERADIUS_SITES_COA_PORT} + } + } + + # Receive a CoA request + recv CoA-Request { + ok + } + + # Send a CoA ACK + send CoA-ACK { + ok + } + + # Send a CoA NAK + send CoA-NAK { + ok + } + + # Receive a Disconnect request + recv Disconnect-Request { + ok + } + + # Send a Disconnect ACK + send Disconnect-ACK { + ok + } + + # Send a Disconnect NAK + send Disconnect-NAK { + ok + } +} \ No newline at end of file diff --git a/archive/tls-master b/archive/tls-master new file mode 100644 index 0000000..5271f55 --- /dev/null +++ b/archive/tls-master @@ -0,0 +1,247 @@ +###################################################################### +# +# RADIUS over TLS +# +###################################################################### + +server radsec { + listen { + transport = tls + + type = Access-Request + type = Accounting-Request + + tls { + + ipaddr = $ENV{FREERADIUS_SITES_TLS_LISTEN} + port = $ENV{FREERADIUS_SITES_TLS_PORT} + + # Connection limiting for sockets with "proto = tcp". + # + limit { + # Limit the number of simultaneous TCP connections to the socket + # + # The default is 16. + # Setting this to 0 means "no limit" + max_connections = 16 + + # The per-socket "max_requests" option does not exist. + + # The lifetime, in seconds, of a TCP connection. After this lifetime, the connection will be closed. + # + # Setting this to 0 means "forever". + lifetime = 0 + + # The idle timeout, in seconds, of a TCP connection. + # If no packets have been received over the connection for this time, the connection will be closed. + # Setting this to 0 means "no timeout". + # + # We STRONGLY RECOMMEND that you set an idle timeout. + idle_timeout = 30 + } + + private_key_password = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD} + private_key_file = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_FILE} + + # If Private key & Certificate are located in the same file, then private_key_file & + # certificate_file must contain the same file name. + # + # If ca_file (below) is not used, then the certificate_file below MUST include not only the server certificate, but ALSO all + # of the CA certificates used to sign the server certificate. + certificate_file = $ENV{FREERADIUS_SITES_TLS_CERTIFICATE_FILE} + + # Trusted Root CA list + # + # ALL of the CA's in this list will be trusted to issue client certificates for authentication. + # + # In general, you should use self-signed certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain *one* CA certificate. + # + # This parameter is used only for EAP-TLS, when you issue client certificates. If you do not use client certificates, and you do not want + # to permit EAP-TLS authentication, then delete this configuration item. + ca_file = $ENV{FREERADIUS_SITES_TLS_CA_FILE} + + # + # For DH cipher suites to work, you have to run OpenSSL to create the DH file first: + # + # openssl dhparam -out certs/dh 1024 + dh_file = ${certdir}/dh + + # + # If your system doesn't have /dev/urandom, you will need to create this file, and periodically change its contents. + # For security reasons, FreeRADIUS doesn't write to files in its configuration directory. + # random_file = /dev/urandom + + # + # The default fragment size is 1K. However, it's possible to send much more data than that over a TCP connection. The upper limit is 64K. + # Setting the fragment size to more than 1K means that there are fewer round trips when setting up a TLS connection. But only if the certificates are large. + fragment_size = 8192 + + # include_length is a flag which is by default set to yes If set to yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the message is included ONLY in the First packet of a fragment series. + # include_length = yes + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash '. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the line below. + # 5) Restart radiusd + # check_crl = yes + ca_path = ${cadir} + + # Accept an expired Certificate Revocation List + # + # allow_expired_crl = no + + # Accept a not-yet-valid Certificate Revocation List + # + # allow_not_yet_valid_crl = no + + # + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # This check can be done more generally by checking + # the value of the TLS-Client-Cert-Issuer attribute. + # This check can be done via any mechanism you choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # This check can be done more generally by checking + # the value of the TLS-Client-Cert-Common-Name attribute. + # This check can be done via any mechanism you choose. + # + # check_cert_cn = %{User-Name} + # + # Set this option to specify the allowed + # TLS cipher suites. The format is listed + # in "man 1 ciphers". + cipher_list = "DEFAULT" + + # If enabled, OpenSSL will use server cipher list + # (possibly defined by cipher_list option above) + # for choosing right cipher suite rather than + # using client-specified list which is OpenSSl default + # behavior. Having it set to 'yes' is best practice + # for TLS. + cipher_server_preference = yes + + # + # Session resumption / fast reauthentication + # cache. + # + # The cache contains the following information: + # + # session Id - unique identifier, managed by SSL + # User-Name - from the Access-Accept + # Stripped-User-Name - from the Access-Request + # Cached-Session-Policy - from the Access-Accept + # + # The "Cached-Session-Policy" is the name of a + # policy which should be applied to the cached + # session. This policy can be used to assign + # VLANs, IP addresses, etc. It serves as a useful + # way to re-apply the policy from the original + # Access-Accept to the subsequent Access-Accept + # for the cached session. + # + # On session resumption, these attributes are + # copied from the cache, and placed into the + # reply list. + # + # You probably also want "use_tunneled_reply = yes" + # when using fast session resumption. + # + cache { + # + # Lifetime of the cached entries, in hours. + # The sessions will be deleted after this + # time. + # + lifetime = 24 # hours + + # + # Internal "name" of the session cache. + # Used to distinguish which TLS context + # sessions belong to. + # + # The server will generate a random value + # if unset. This will change across server + # restart so you MUST set the "name" if you + # want to persist sessions (see below). + # + # If you use IPv6, change the "ipaddr" below + # to "ipv6addr" + # + #name = "TLS ${..ipaddr} ${..port} ${..proto}" + + # + # Simple directory-based storage of sessions. + # Two files per session will be written, the SSL + # state and the cached VPs. This will persist session + # across server restarts. + # + # The server will need write perms, and the directory + # should be secured from anyone else. You might want + # a script to remove old files from here periodically: + # + # find ${logdir}/tlscache -mtime +2 -exec rm -f {} \; + # + # This feature REQUIRES "name" option be set above. + # + #persist_dir = "${logdir}/tlscache" + } + + # Require a client certificate. + # + require_client_cert = yes + + # + # As of version 2.1.10, client certificates can be validated via an external command. This allows dynamic CRLs or OCSP to be used. + # + # This configuration is commented out in the default configuration. Uncomment it, and configure the correct paths below to enable it. + # + verify { + # A temporary directory where the client certificates are stored. This directory MUST be owned by the UID of the server, + # and MUST not be accessible by any other users. When the server starts, it will do "chmod go-rwx" on the directory, for + # security reasons. The directory MUST exist when the server starts. + # + # You should also delete all of the files in the directory when the server starts. + tmpdir = /startechnica/freeradius/tmp + + # The command used to verify the client cert. We recommend using the OpenSSL command-line tool. + # + # The ${..ca_path} text is a reference to the ca_path variable defined above. + # + # The %{TLS-Client-Cert-Filename} is the name of the temporary file containing the cert in PEM format. This file is automatically + # deleted by the server when the command returns. + # client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" + } + } + } + + recv Access-Request { + ok + } + + recv Accounting-Request { + ok + } +} \ No newline at end of file diff --git a/charts/mariadb-20.5.9.tgz b/charts/mariadb-20.5.9.tgz new file mode 100644 index 0000000..017dc9c Binary files /dev/null and b/charts/mariadb-20.5.9.tgz differ diff --git a/charts/st-common-0.1.12.tgz b/charts/st-common-0.1.12.tgz new file mode 100644 index 0000000..f32e3fe Binary files /dev/null and b/charts/st-common-0.1.12.tgz differ diff --git a/files/docker-entrypoint-initdb.d/README.md b/files/docker-entrypoint-initdb.d/README.md new file mode 100644 index 0000000..36e0679 --- /dev/null +++ b/files/docker-entrypoint-initdb.d/README.md @@ -0,0 +1,3 @@ +You can copy here your custom .sh, .sql or .sql.gz file so they are executed during the first boot of the image. + +More info in the [freeradius/freeradius-server](https://hub.docker.com/r/freeradius/freeradius-server) repository. \ No newline at end of file diff --git a/files/mods-available/sql b/files/mods-available/sql new file mode 100644 index 0000000..7c75c6c --- /dev/null +++ b/files/mods-available/sql @@ -0,0 +1,366 @@ +# -*- text -*- +## +## mods-available/sql -- SQL modules +## +## $Id: cfeac63ea87c30fead8457af6d10f5c3a0f48aef $ + +###################################################################### +# +# Configuration for the SQL module +# +# The database schemas and queries are located in subdirectories: +# +# sql//main/schema.sql Schema +# sql//main/queries.conf Authorisation and Accounting queries +# +# Where "DB" is mysql, mssql, oracle, or postgresql. +# +# The name used to query SQL is sql_user_name, which is set in the file +# +# raddb/mods-config/sql/main/${dialect}/queries.conf +# +# If you are using realms, that configuration should be changed to use +# the Stripped-User-Name attribute. See the comments around sql_user_name +# for more information. +# + +sql { + # + # The dialect of SQL being used. + # + # Allowed dialects are: + # + # mssql + # mysql + # oracle + # postgresql + # sqlite + # mongo + # +# dialect = "sqlite" + dialect = $ENV{FREERADIUS_MODS_SQL_DIALECT} + + # + # The driver module used to execute the queries. Since we + # don't know which SQL drivers are being used, the default is + # "rlm_sql_null", which just logs the queries to disk via the + # "logfile" directive, below. + # + # In order to talk to a real database, delete the next line, + # and uncomment the one after it. + # + # If the dialect is "mssql", then the driver should be set to + # one of the following values, depending on your system: + # + # rlm_sql_db2 + # rlm_sql_firebird + # rlm_sql_freetds + # rlm_sql_iodbc + # rlm_sql_unixodbc + # +# driver = "rlm_sql_null" + driver = "rlm_sql_${dialect}" + + # + # Driver-specific subsections. They will only be loaded and + # used if "driver" is something other than "rlm_sql_null". + # When a real driver is used, the relevant driver + # configuration section is loaded, and all other driver + # configuration sections are ignored. + # + sqlite { + # Path to the sqlite database + filename = $ENV{FREERADIUS_MODS_SQL_SQLITE_FILENAME} + + # How long to wait for write locks on the database to be released (in ms) before giving up. + busy_timeout = $ENV{FREERADIUS_MODS_SQL_SQLITE_BUSY_TIMEOUT} + + # If the file above does not exist and bootstrap is set + # a new database file will be created, and the SQL statements + # contained within the bootstrap file will be executed. + bootstrap = "${modconfdir}/${..:name}/main/sqlite/schema.sql" + } + + mysql { + # If any of the files below are set, TLS encryption is enabled + tls { +# ca_file = $ENV{FREERADIUS_MODS_SQL_TLS_CACERT} +# ca_path = "/startechnica/freeradius/certs-sql/" +# certificate_file = $ENV{FREERADIUS_MODS_SQL_TLS_CERTIFICATE} +# private_key_file = $ENV{FREERADIUS_MODS_SQL_TLS_PRIVATEKEY} +# cipher = "DHE-RSA-AES256-SHA:AES128-SHA" +# cipher = $ENV{FREERADIUS_MODS_SQL_TLS_CIPHER} + + tls_required = $ENV{FREERADIUS_MODS_SQL_TLS_ENABLE} + tls_check_cert = no + tls_check_cert_cn = no + } + + # If yes, (or auto and libmysqlclient reports warnings are + # available), will retrieve and log additional warnings from + # the server if an error has occured. Defaults to 'auto' + warnings = auto + } + + postgresql { + + # unlike MySQL, which has a tls{} connection configuration, postgresql + # uses its connection parameters - see the radius_db option below in + # this file + + # Send application_name to the postgres server + # Only supported in PG 9.0 and greater. Defaults to no. + send_application_name = yes + } + + # + # Configuration for Mongo. + # + # Note that the Mongo driver is experimental. The FreeRADIUS developers + # are unable to help with the syntax of the Mongo queries. Please see + # the Mongo documentation for that syntax. + # + # The Mongo driver supports only the following methods: + # + # aggregate + # findAndModify + # findOne + # insert + # + # For examples, see the query files: + # + # raddb/mods-config/sql/main/mongo/queries.conf + # raddb/mods-config/sql/main/ippool/queries.conf + # + # In order to use findAndModify with an aggretation pipleline, make + # sure that you are running MongoDB version 4.2 or greater. FreeRADIUS + # assumes that the paramaters passed to the methods are supported by the + # version of MongoDB which it is connected to. + # + mongo { + # + # The application name to use. + # + appname = "freeradius" + + # + # The TLS parameters here map directly to the Mongo TLS configuration + # + tls { + certificate_file = $ENV{FREERADIUS_MODS_SQL_TLS_CERTIFICATE} + certificate_password = $ENV{FREERADIUS_MODS_SQL_TLS_PRIVATEKEY} + ca_file = $ENV{FREERADIUS_MODS_SQL_TLS_CACERT} + ca_dir = /startechnica/freeradius/certs-sql/ + # crl_file = /path/to/file + weak_cert_validation = false + allow_invalid_hostname = false + } + } + + # Connection info: + # + server = $ENV{FREERADIUS_MODS_SQL_SERVER} + port = $ENV{FREERADIUS_MODS_SQL_PORT} + login = $ENV{FREERADIUS_MODS_SQL_LOGIN} + password = $ENV{FREERADIUS_MODS_SQL_PASSWORD} + + # Connection info for Mongo + # Authentication Without SSL + # server = "mongodb://USER:PASSWORD@192.16.0.2:PORT/DATABASE?authSource=admin&ssl=false" + + # Authentication With SSL + # server = "mongodb://USER:PASSWORD@192.16.0.2:PORT/DATABASE?authSource=admin&ssl=true" + + # Authentication with Certificate + # Use this command for retrieve Derived username: + # openssl x509 -in mycert.pem -inform PEM -subject -nameopt RFC2253 + # server = mongodb://@192.168.0.2:PORT/DATABASE?authSource=$external&ssl=true&authMechanism=MONGODB-X509 + + # Database table configuration for everything except Oracle + radius_db = $ENV{FREERADIUS_MODS_SQL_DB} + + # If you are using Oracle then use this instead +# radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))" + + # If you're using postgresql this can also be used instead of the connection info parameters +# radius_db = "dbname=$ENV{FREERADIUS_MODS_SQL_DB} host=$ENV{FREERADIUS_MODS_SQL_SERVER} port=$ENV{FREERADIUS_MODS_SQL_PORT} user=$ENV{FREERADIUS_MODS_SQL_LOGIN} password=$ENV{FREERADIUS_MODS_SQL_PASSWORD}" + + # Postgreql doesn't take tls{} options in its module config like mysql does - if you want to + # use SSL connections then use this form of connection info parameter +# radius_db = "host=localhost port=5432 dbname=radius user=radius password=raddpass sslmode=verify-full sslcert=/etc/ssl/client.crt sslkey=/etc/ssl/client.key sslrootcert=/etc/ssl/ca.crt" + + # If you want both stop and start records logged to the + # same SQL table, leave this as is. If you want them in + # different tables, put the start table in acct_table1 + # and stop table in acct_table2 + acct_table1 = $ENV{FREERADIUS_MODS_SQL_TABLE_ACCT1} + acct_table2 = $ENV{FREERADIUS_MODS_SQL_TABLE_ACCT2} + + # Allow for storing data after authentication + postauth_table = $ENV{FREERADIUS_MODS_SQL_TABLE_POSTAUTH} + + # Tables containing 'check' items + authcheck_table = $ENV{FREERADIUS_MODS_SQL_TABLE_AUTHCHECK} + groupcheck_table = $ENV{FREERADIUS_MODS_SQL_TABLE_GROUPCHECK} + + # Tables containing 'reply' items + authreply_table = $ENV{FREERADIUS_MODS_SQL_TABLE_AUTHREPLY} + groupreply_table = $ENV{FREERADIUS_MODS_SQL_TABLE_GROUPREPLY} + + # Table to keep group info + usergroup_table = $ENV{FREERADIUS_MODS_SQL_TABLE_USERGROUP} + + # If set to 'yes' (default) we read the group tables unless Fall-Through = no in the reply table. + # If set to 'no' we do not read the group tables unless Fall-Through = yes in the reply table. +# read_groups = yes + + # If set to 'yes' (default) we read profiles unless Fall-Through = no in the groupreply table. + # If set to 'no' we do not read profiles unless Fall-Through = yes in the groupreply table. +# read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + # Write SQL queries to a logfile. This is potentially useful for tracing + # issues with authorization queries. See also "logfile" directives in + # mods-config/sql/main/*/queries.conf. You can enable per-section logging + # by enabling "logfile" there, or global logging by enabling "logfile" here. + # + # Per-section logging can be disabled by setting "logfile = ''" +# logfile = ${logdir}/sqllog.sql + + # Set the maximum query duration and connection timeout + # for rlm_sql_mysql. +# query_timeout = 5 + + # As of version 3.0, the "pool" section has replaced the + # following configuration items: + # + # num_sql_socks + # connect_failure_retry_delay + # lifetime + # max_queries + + # + # The connection pool is new for 3.0, and will be used in many + # modules, for all kinds of connection-related activity. + # + # When the server is not threaded, the connection pool + # limits are ignored, and only one connection is used. + # + # If you want to have multiple SQL modules re-use the same + # connection pool, use "pool = name" instead of a "pool" + # section. e.g. + # + # sql sql1 { + # ... + # pool { + # ... + # } + # } + # + # # sql2 will use the connection pool from sql1 + # sql sql2 { + # ... + # pool = sql1 + # } + # + pool { + # Connections to create during module instantiation. + # If the server cannot create specified number of + # connections during instantiation it will exit. + # Set to 0 to allow the server to start without the database being available. + start = ${thread[pool].start_servers} + + # Minimum number of connections to keep open + min = ${thread[pool].min_spare_servers} + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = ${thread[pool].max_servers} + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if "idle_timeout" + # is set. This should be less than or equal to "max" above. + spare = ${thread[pool].max_spare_servers} + + # Number of uses before the connection is closed + # + # 0 means "infinite" + uses = 0 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + retry_delay = 30 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of "idle_timeout", + # "uses", or "lifetime", then the total number of + # connections MAY fall below "min". When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the "min" connections, + # or increase lifetime/idle_timeout. + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. + # + # A client can be link to a virtual server via the SQL + # module. This link is done via the following process: + # + # If there is no listener in a virtual server, SQL clients + # are added to the global list for that virtual server. + # + # If there is a listener, and the first listener does not + # have a "clients=..." configuration item, SQL clients are + # added to the global list. + # + # If there is a listener, and the first one does have a + # "clients=..." configuration item, SQL clients are added to + # that list. The client { ...} ` configured in that list are + # also added for that listener. + # + # The only issue is if you have multiple listeners in a + # virtual server, each with a different client list, then + # the SQL clients are added only to the first listener. + # + read_clients = $ENV{FREERADIUS_MODS_SQL_READ_CLIENTS} + + # Table to keep radius client info + client_table = $ENV{FREERADIUS_MODS_SQL_TABLE_CLIENT} + + # + # The group attribute specific to this instance of rlm_sql + # + + # This entry should be used for additional instances (sql foo {}) + # of the SQL module. +# group_attribute = "${.:instance}-SQL-Group" + + # This entry should be used for the default instance (sql {}) + # of the SQL module. + group_attribute = $ENV{FREERADIUS_MODS_SQL_GROUP_ATTRIBUTE} + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} \ No newline at end of file diff --git a/files/schema/mysql.sql b/files/schema/mysql.sql new file mode 100644 index 0000000..ef78b2b --- /dev/null +++ b/files/schema/mysql.sql @@ -0,0 +1,165 @@ +########################################################################### +# $Id: 41fcccad1c012226d12cc721518fe91e311e55e2 $ # +# # +# schema.sql rlm_sql - FreeRADIUS SQL Module # +# # +# Database schema for MySQL rlm_sql module # +# # +# To load: # +# mysql -uroot -prootpass radius < schema.sql # +# # +# Mike Machado # +########################################################################### + +# +# Table structure for table 'radacct' +# +CREATE TABLE IF NOT EXISTS radacct ( + radacctid bigint(21) NOT NULL auto_increment, + acctsessionid varchar(64) NOT NULL default '', + acctuniqueid varchar(32) NOT NULL default '', + username varchar(64) NOT NULL default '', + realm varchar(64) default '', + nasipaddress varchar(15) NOT NULL default '', + nasportid varchar(32) default NULL, + nasporttype varchar(32) default NULL, + acctstarttime datetime NULL default NULL, + acctupdatetime datetime NULL default NULL, + acctstoptime datetime NULL default NULL, + acctinterval int(12) default NULL, + acctsessiontime int(12) unsigned default NULL, + acctauthentic varchar(32) default NULL, + connectinfo_start varchar(128) default NULL, + connectinfo_stop varchar(128) default NULL, + acctinputoctets bigint(20) default NULL, + acctoutputoctets bigint(20) default NULL, + calledstationid varchar(50) NOT NULL default '', + callingstationid varchar(50) NOT NULL default '', + acctterminatecause varchar(32) NOT NULL default '', + servicetype varchar(32) default NULL, + framedprotocol varchar(32) default NULL, + framedipaddress varchar(15) NOT NULL default '', + framedipv6address varchar(45) NOT NULL default '', + framedipv6prefix varchar(45) NOT NULL default '', + framedinterfaceid varchar(44) NOT NULL default '', + delegatedipv6prefix varchar(45) NOT NULL default '', + class varchar(64) default NULL, + PRIMARY KEY (radacctid), + UNIQUE KEY acctuniqueid (acctuniqueid), + KEY username (username), + KEY framedipaddress (framedipaddress), + KEY framedipv6address (framedipv6address), + KEY framedipv6prefix (framedipv6prefix), + KEY framedinterfaceid (framedinterfaceid), + KEY delegatedipv6prefix (delegatedipv6prefix), + KEY acctsessionid (acctsessionid), + KEY acctsessiontime (acctsessiontime), + KEY acctstarttime (acctstarttime), + KEY acctinterval (acctinterval), + KEY acctstoptime (acctstoptime), + KEY nasipaddress (nasipaddress), + KEY class (class) +) ENGINE = INNODB; + +# +# Table structure for table 'radcheck' +# +CREATE TABLE IF NOT EXISTS radcheck ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '==', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY username (username(32)) +) ENGINE = INNODB; + +# +# Table structure for table 'radgroupcheck' +# +CREATE TABLE IF NOT EXISTS radgroupcheck ( + id int(11) unsigned NOT NULL auto_increment, + groupname varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '==', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY groupname (groupname(32)) +) ENGINE = INNODB; + +# +# Table structure for table 'radgroupreply' +# +CREATE TABLE IF NOT EXISTS radgroupreply ( + id int(11) unsigned NOT NULL auto_increment, + groupname varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '=', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY groupname (groupname(32)) +) ENGINE = INNODB; + +# +# Table structure for table 'radreply' +# +CREATE TABLE IF NOT EXISTS radreply ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + attribute varchar(64) NOT NULL default '', + op char(2) NOT NULL DEFAULT '=', + value varchar(253) NOT NULL default '', + PRIMARY KEY (id), + KEY username (username(32)) +) ENGINE = INNODB; + + +# +# Table structure for table 'radusergroup' +# +CREATE TABLE IF NOT EXISTS `radusergroup` ( + id int(11) unsigned NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + groupname varchar(64) NOT NULL default '', + priority int(11) NOT NULL default '1', + PRIMARY KEY (id), + KEY username (username(32)) +) ENGINE = INNODB; + +# +# Table structure for table 'radpostauth' +# +# Note: MySQL versions since 5.6.4 support fractional precision timestamps +# which we use here. Replace the authdate definition with the following +# if your software is too old: +# +# authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +# +CREATE TABLE IF NOT EXISTS radpostauth ( + id int(11) NOT NULL auto_increment, + username varchar(64) NOT NULL default '', + pass varchar(64) NOT NULL default '', + reply varchar(32) NOT NULL default '', + authdate timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), + class varchar(64) default NULL, + PRIMARY KEY (id), + KEY username (username), + KEY class (class) +) ENGINE = INNODB; + +# +# Table structure for table 'nas' +# +CREATE TABLE IF NOT EXISTS nas ( + id int(10) NOT NULL auto_increment, + nasname varchar(128) NOT NULL, + shortname varchar(32), + type varchar(30) DEFAULT 'other', + ports int(5), + secret varchar(60) DEFAULT 'secret' NOT NULL, + server varchar(64), + community varchar(50), + description varchar(200) DEFAULT 'RADIUS Client', + PRIMARY KEY (id), + KEY nasname (nasname) +) ENGINE = INNODB; diff --git a/files/sites-available/coa b/files/sites-available/coa new file mode 100644 index 0000000..85849a8 --- /dev/null +++ b/files/sites-available/coa @@ -0,0 +1,41 @@ +# -*- text -*- +###################################################################### +# +# Sample virtual server for receiving a CoA or Disconnect-Request packet. +# + +# Listen on the CoA port. +# +# This uses the normal set of clients, with the same secret as for authentication and accounting. +# + +listen { + type = coa + # ipaddr = $ENV{FREERADIUS_SITES_COA_LISTEN} + ipaddr = * + port = $ENV{FREERADIUS_SITES_COA_PORT} + virtual_server = coa +} + +server coa { + # When a packet is received, it is processed through the recv-coa section. This applies to *both* CoA-Request and Disconnect-Request packets. + recv-coa { + # CoA && Disconnect packets can be proxied in the same way as authentication or accounting packets. + # Just set Proxy-To-Realm, or Home-Server-Pool, and the packets will be proxied. + + # Do proxying based on realms here. You don't need "IPASS" or "ntdomain", as the proxying is based on the Operator-Name attribute. It contains the realm, + # and ONLY the realm (prefixed by a '1') + suffix + + # Insert your own policies here. + ok + } + + # When a packet is sent, it is processed through the send-coa section. This applies to *both* CoA-Request and Disconnect-Request packets. + send-coa { + # Sample module. + ok + } + + # You can use pre-proxy and post-proxy sections here, too. They will be processed for sending && receiving proxy packets. +} \ No newline at end of file diff --git a/files/sites-available/default b/files/sites-available/default new file mode 100644 index 0000000..a5d37af --- /dev/null +++ b/files/sites-available/default @@ -0,0 +1,1072 @@ +###################################################################### +# +# As of 2.0.0, FreeRADIUS supports virtual hosts using the +# "server" section, and configuration directives. +# +# Virtual hosts should be put into the "sites-available" +# directory. Soft links should be created in the "sites-enabled" +# directory to these files. This is done in a normal installation. +# +# If you are using 802.1X (EAP) authentication, please see also +# the "inner-tunnel" virtual server. You will likely have to edit +# that, too, for authentication to work. +# +# $Id: 1926b7cd6e381cebfb809c7e89f8db0808124625 $ +# +###################################################################### +# +# Read "man radiusd" before editing this file. See the section +# titled DEBUGGING. It outlines a method where you can quickly +# obtain the configuration you want, without running into +# trouble. See also "man unlang", which documents the format +# of this file. +# +# This configuration is designed to work in the widest possible +# set of circumstances, with the widest possible number of +# authentication methods. This means that in general, you should +# need to make very few changes to this file. +# +# The best way to configure the server for your local system +# is to CAREFULLY edit this file. Most attempts to make large +# edits to this file will BREAK THE SERVER. Any edits should +# be small, and tested by running the server with "radiusd -X". +# Once the edits have been verified to work, save a copy of these +# configuration files somewhere. (e.g. as a "tar" file). Then, +# make more edits, and test, as above. +# +# There are many "commented out" references to modules such +# as ldap, sql, etc. These references serve as place-holders. +# If you need the functionality of that module, then configure +# it in radiusd.conf, and un-comment the references to it in +# this file. In most cases, those small changes will result +# in the server being able to connect to the DB, and to +# authenticate users. +# +###################################################################### + +server default { +# +# If you want the server to listen on additional addresses, or on +# additional ports, you can use multiple "listen" sections. +# +# Each section make the server listen for only one type of packet, +# therefore authentication and accounting have to be configured in +# different sections. +# +# The server ignore all "listen" section if you are using '-i' and '-p' +# on the command line. +# +listen { + # Type of packets to listen for. + # Allowed values are: + # auth listen for authentication packets + # acct listen for accounting packets + # auth+acct listen for both authentication and accounting packets + # proxy IP to use for sending proxied packets + # detail Read from the detail file. For examples, see + # raddb/sites-available/copy-acct-to-home-server + # status listen for Status-Server packets. For examples, + # see raddb/sites-available/status + # coa listen for CoA-Request and Disconnect-Request + # packets. For examples, see the file + # raddb/sites-available/coa + # + type = auth + + # Note: "type = proxy" lets you control the source IP used for + # proxying packets, with some limitations: + # + # * A proxy listener CANNOT be used in a virtual server section. + # * You should probably set "port = 0". + # * Any "clients" configuration will be ignored. + # + # See also proxy.conf, and the "src_ipaddr" configuration entry + # in the sample "home_server" section. When you specify the + # source IP address for packets sent to a home server, the + # proxy listeners are automatically created. + + # ipaddr/ipv4addr/ipv6addr - IP address on which to listen. + # If multiple ones are listed, only the first one will + # be used, and the others will be ignored. + # + # The configuration options accept the following syntax: + # + # ipv4addr - IPv4 address (e.g.192.0.2.3) + # - wildcard (i.e. *) + # - hostname (radius.example.com) + # Only the A record for the host name is used. + # If there is no A record, an error is returned, + # and the server fails to start. + # + # ipv6addr - IPv6 address (e.g. 2001:db8::1) + # - wildcard (i.e. *) + # - hostname (radius.example.com) + # Only the AAAA record for the host name is used. + # If there is no AAAA record, an error is returned, + # and the server fails to start. + # + # ipaddr - IPv4 address as above + # - IPv6 address as above + # - wildcard (i.e. *), which means IPv4 wildcard. + # - hostname + # If there is only one A or AAAA record returned + # for the host name, it is used. + # If multiple A or AAAA records are returned + # for the host name, only the first one is used. + # If both A and AAAA records are returned + # for the host name, only the A record is used. + # + # ipv4addr = * + # ipv6addr = * + ipaddr = * + + # Port on which to listen. + # Allowed values are: + # integer port number (1812) + # 0 means "use /etc/services for the proper port" + port = $ENV{FREERADIUS_SITES_DEFAULT_AUTH_PORT} + + # Some systems support binding to an interface, in addition + # to the IP address. This feature isn't strictly necessary, + # but for sites with many IP addresses on one interface, + # it's useful to say "listen on all addresses for eth0". + # + # If your system does not support this feature, you will + # get an error if you try to use it. + # +# interface = eth0 + + # Per-socket lists of clients. This is a very useful feature. + # + # The name here is a reference to a section elsewhere in + # radiusd.conf, or clients.conf. Having the name as + # a reference allows multiple sockets to use the same + # set of clients. + # + # If this configuration is used, then the global list of clients + # is IGNORED for this "listen" section. Take care configuring + # this feature, to ensure you don't accidentally disable a + # client you need. + # + # See clients.conf for the configuration of "per_socket_clients". + # +# clients = per_socket_clients + + # + # Set the default UDP receive buffer size. In most cases, + # the default values set by the kernel are fine. However, in + # some cases the NASes will send large packets, and many of + # them at a time. It is then possible to overflow the + # buffer, causing the kernel to drop packets before they + # reach FreeRADIUS. Increasing the size of the buffer will + # avoid these packet drops. + # +# recv_buff = 65536 + + # + # Connection limiting for sockets with "proto = tcp". + # + # This section is ignored for other kinds of sockets. + # + limit { + # + # Limit the number of simultaneous TCP connections to the socket + # + # The default is 16. + # Setting this to 0 means "no limit" + max_connections = 16 + + # The per-socket "max_requests" option does not exist. + + # + # The lifetime, in seconds, of a TCP connection. After + # this lifetime, the connection will be closed. + # + # Setting this to 0 means "forever". + lifetime = 0 + + # + # The idle timeout, in seconds, of a TCP connection. + # If no packets have been received over the connection for + # this time, the connection will be closed. + # + # Setting this to 0 means "no timeout". + # + # We STRONGLY RECOMMEND that you set an idle timeout. + # + idle_timeout = 30 + } +} + +# +# This second "listen" section is for listening on the accounting +# port, too. +# +listen { + ipaddr = * +# ipv6addr = :: + port = $ENV{FREERADIUS_SITES_DEFAULT_ACCT_PORT} + type = acct +# interface = eth0 +# clients = per_socket_clients + + limit { + # The number of packets received can be rate limited via the + # "max_pps" configuration item. When it is set, the server + # tracks the total number of packets received in the previous + # second. If the count is greater than "max_pps", then the + # new packet is silently discarded. This helps the server + # deal with overload situations. + # + # The packets/s counter is tracked in a sliding window. This + # means that the pps calculation is done for the second + # before the current packet was received. NOT for the current + # wall-clock second, and NOT for the previous wall-clock second. + # + # Useful values are 0 (no limit), or 100 to 10000. + # Values lower than 100 will likely cause the server to ignore + # normal traffic. Few systems are capable of handling more than + # 10K packets/s. + # + # It is most useful for accounting systems. Set it to 50% + # more than the normal accounting load, and you can be sure that + # the server will never get overloaded + # +# max_pps = 0 + + # Only for "proto = tcp". These are ignored for "udp" sockets. + # +# idle_timeout = 0 +# lifetime = 0 +# max_connections = 0 + } +} + +# IPv6 versions of the above - read their full config to understand options +listen { + type = auth + ipv6addr = :: # any. ::1 == localhost + port = $ENV{FREERADIUS_SITES_DEFAULT_AUTH_PORT} +# interface = eth0 +# clients = per_socket_clients + limit { + max_connections = 16 + lifetime = 0 + idle_timeout = 30 + } +} + +listen { + ipv6addr = :: + port = $ENV{FREERADIUS_SITES_DEFAULT_ACCT_PORT} + type = acct +# interface = eth0 +# clients = per_socket_clients + limit { + max_pps = 0 + idle_timeout = 0 + lifetime = 0 + max_connections = 0 + } +} + +# Authorization. First preprocess (hints and huntgroups files), +# then realms, and finally look in the "users" file. +# +# Any changes made here should also be made to the "inner-tunnel" +# virtual server. +# +# The order of the realm modules will determine the order that +# we try to find a matching realm. +# +# Make *sure* that 'preprocess' comes before any realm if you +# need to setup hints for the remote radius server +authorize { + # + # Take a User-Name, and perform some checks on it, for spaces and other + # invalid characters. If the User-Name appears invalid, reject the + # request. + # + # See policy.d/filter for the definition of the filter_username policy. + # + filter_username + + # + # Some broken equipment sends passwords with embedded zeros. + # i.e. the debug output will show + # + # User-Password = "password\000\000" + # + # This policy will fix it to just be "password". + # +# filter_password + + # + # The preprocess module takes care of sanitizing some bizarre + # attributes in the request, and turning them into attributes + # which are more standard. + # + # It takes care of processing the 'raddb/mods-config/preprocess/hints' + # and the 'raddb/mods-config/preprocess/huntgroups' files. + preprocess + + # If you intend to use CUI and you require that the Operator-Name + # be set for CUI generation and you want to generate CUI also + # for your local clients then uncomment the operator-name + # below and set the operator-name for your clients in clients.conf +# operator-name + + # + # If you want to generate CUI for some clients that do not + # send proper CUI requests, then uncomment the + # cui below and set "add_cui = yes" for these clients in clients.conf +# cui + + # + # If you want to have a log of authentication requests, + # un-comment the following line. +# auth_log + + # + # The chap module will set 'Auth-Type := CHAP' if we are + # handling a CHAP request and Auth-Type has not already been set + chap + + # + # If the users are logging in with an MS-CHAP-Challenge + # attribute for authentication, the mschap module will find + # the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP' + # to the request, which will cause the server to then use + # the mschap module for authentication. + mschap + + # + # If you have a Cisco SIP server authenticating against + # FreeRADIUS, uncomment the following line, and the 'digest' + # line in the 'authenticate' section. + digest + + # + # The WiMAX specification says that the Calling-Station-Id + # is 6 octets of the MAC. This definition conflicts with + # RFC 3580, and all common RADIUS practices. If you are using + # old style WiMAX (non LTE) the un-commenting the "wimax" module + # here means that it will fix the Calling-Station-Id attribute to + # the normal format as specified in RFC 3580 Section 3.21. + # + # If you are using WiMAX 2.1 (LTE) then un-commenting will allow + # the module to handle SQN resyncronisation. Prior to calling the + # module it is necessary to populate the following attributes + # with the relevant keys: + # control:WiMAX-SIM-Ki + # control:WiMAX-SIM-OPc + # + # If WiMAX-Re-synchronization-Info is found in the request then + # the module will attempt to extract SQN and store it in + # control:WiMAX-SIM-SQN. Also a copy of RAND is extracted to + # control:WiMAX-SIM-RAND. + # + # If the SIM cannot be authenticated using Ki and OPc then reject + # will be returned. +# wimax + + # + # Look for IPASS style 'realm/', and if not found, look for + # '@realm', and decide whether or not to proxy, based on + # that. +# IPASS + + # + # Look for realms in user@domain format + suffix +# ntdomain + + # + # This module takes care of EAP-MD5, EAP-TLS, and EAP-LEAP + # authentication. + # + # It also sets the EAP-Type attribute in the request + # attribute list to the EAP type from the packet. + # + # The EAP module returns "ok" or "updated" if it is not yet ready + # to authenticate the user. The configuration below checks for + # "ok", and stops processing the "authorize" section if so. + # + # Any LDAP and/or SQL servers will not be queried for the + # initial set of packets that go back and forth to set up + # TTLS or PEAP. + # + # The "updated" check is commented out for compatibility with + # previous versions of this configuration, but you may wish to + # uncomment it as well; this will further reduce the number of + # LDAP and/or SQL queries for TTLS or PEAP. + # + eap { + ok = return +# updated = return + } + + # Pull crypt'd passwords from /etc/passwd or /etc/shadow, using the system API's to get the password. If you want + # to read /etc/passwd or /etc/shadow directly, see the mods-available/passwd module. +# unix + + # Read the 'users' file. In v3, this is located in raddb/mods-config/files/authorize + files + + # Look in an SQL database. The schema of the database is meant to mirror the "users" file. + # + # See "Authorization Queries" in mods-available/sql + -sql + + # If you are using /etc/smbpasswd, and are also doing mschap authentication, the un-comment this line, and configure the 'smbpasswd' module. +# smbpasswd + + # The ldap module reads passwords from the LDAP database. + -ldap + + # Enforce daily limits on time spent logged in. +# daily + + # + expiration + logintime + + # + # If no other module has claimed responsibility for + # authentication, then try to use PAP. This allows the + # other modules listed above to add a "known good" password + # to the request, and to do nothing else. The PAP module + # will then see that password, and use it to do PAP + # authentication. + # + # This module should be listed last, so that the other modules + # get a chance to set Auth-Type for themselves. + # + pap + + # If "status_server = yes", then Status-Server messages are passed through the following section, and ONLY the following section. + # This permits you to do DB queries, for example. If the modules listed here return "fail", then NO response is sent. +# Autz-Type Status-Server { +# +# } + + # + # RADIUS/TLS (or RadSec) connections are processed through + # this section. See sites-available/tls, and the configuration + # item "check_client_connections" for more information. + # + # The request contains TLS client certificate attributes, + # and nothing else. The debug output will print which + # attributes are available on your system. + # + # If the section returns "ok" or "updated", then the + # connection is accepted. Otherwise the connection is + # terminated. + # + Autz-Type New-TLS-Connection { + ok + } +} + + +# Authentication. +# +# +# This section lists which modules are available for authentication. +# Note that it does NOT mean 'try each module in order'. It means +# that a module from the 'authorize' section adds a configuration +# attribute 'Auth-Type := FOO'. That authentication type is then +# used to pick the appropriate module from the list below. +# + +# In general, you SHOULD NOT set the Auth-Type attribute. The server +# will figure it out on its own, and will do the right thing. The +# most common side effect of erroneously setting the Auth-Type +# attribute is that one authentication method will work, but the +# others will not. +# +# The common reasons to set the Auth-Type attribute by hand +# is to either forcibly reject the user (Auth-Type := Reject), +# or to or forcibly accept the user (Auth-Type := Accept). +# +# Note that Auth-Type := Accept will NOT work with EAP. +# +# Please do not put "unlang" configurations into the "authenticate" +# section. Put them in the "post-auth" section instead. That's what +# the post-auth section is for. +# +authenticate { + # PAP authentication, when a back-end database listed in the 'authorize' section supplies a password. The password can be clear-text, or encrypted. + Auth-Type PAP { + pap + } + + # Most people want CHAP authentication + # A back-end database listed in the 'authorize' section MUST supply a CLEAR TEXT password. Encrypted passwords won't work. + Auth-Type CHAP { + chap + } + + # MSCHAP authentication. + Auth-Type MS-CHAP { + mschap + } + + # For old names, too. + mschap + + # If you have a Cisco SIP server authenticating against FreeRADIUS, uncomment the following line, and the 'digest' line in the 'authorize' section. + digest + + # Pluggable Authentication Modules. +# pam + + # Uncomment it if you want to use ldap for authentication + # + # Note that this means "check plain-text password against + # the ldap database", which means that EAP won't work, + # as it does not supply a plain-text password. + # + # We do NOT recommend using this. LDAP servers are databases. + # They are NOT authentication servers. FreeRADIUS is an + # authentication server, and knows what to do with authentication. + # LDAP servers do not. + # +# Auth-Type LDAP { +# ldap +# } + + # + # Allow EAP authentication. + eap + + # + # The older configurations sent a number of attributes in + # Access-Challenge packets, which wasn't strictly correct. + # If you want to filter out these attributes, uncomment + # the following lines. + # +# Auth-Type eap { +# eap { +# handled = 1 +# } +# if (handled && (Response-Packet-Type == Access-Challenge)) { +# attr_filter.access_challenge.post-auth +# handled # override the "updated" code from attr_filter +# } +# } +} + + +# Pre-accounting. Decide which accounting type to use. +# +preacct { + preprocess + + # Merge Acct-[Input|Output]-Gigawords and Acct-[Input-Output]-Octets into a single 64bit counter Acct-[Input|Output]-Octets64. +# acct_counters64 + + # Session start times are *implied* in RADIUS. + # The NAS never sends a "start time". Instead, it sends a start packet, *possibly* with an Acct-Delay-Time. + # The server is supposed to conclude that the start time was "Acct-Delay-Time" seconds in the past. + # + # The code below creates an explicit start time, which can then be used in other modules. It will be *mostly* correct. + # Any errors are due to the 1-second resolution of RADIUS, and the possibility that the time on the NAS may be off. + # + # The start time is: NOW - delay - session_length + +# update request { +# &FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}" +# } + + # Ensure that we have a semi-unique identifier for every request, and many NAS boxes are broken. + acct_unique + + # Look for IPASS-style 'realm/', and if not found, look for '@realm', and decide whether or not to proxy, based on that. + # + # Accounting requests are generally proxied to the same + # home server as authentication requests. +# IPASS + suffix +# ntdomain + + # Read the 'acct_users' file + files +} + +# +# Accounting. Log the accounting data. +# +accounting { + # Update accounting packet by adding the CUI attribute recorded from the corresponding Access-Accept use it only if your NAS boxes do not support CUI themselves +# cui + # + # Create a 'detail'ed log of the packets. + # Note that accounting requests which are proxied are also logged in the detail file. + detail +# daily + + # Update the wtmp file + # + # If you don't use "radlast", you can delete this line. + unix + + # For Simultaneous-Use tracking. + # Due to packet losses in the network, the data here may be incorrect. There is little we can do about it. +# radutmp +# sradutmp + + # Return an address to the IP Pool when we see a stop record. + # Ensure that &control:Pool-Name is set to determine which pool of IPs are used. +# sqlippool + + # Log traffic to an SQL database. + # See "Accounting queries" in mods-available/sql + -sql + + # + # If you receive stop packets with zero session length, + # they will NOT be logged in the database. The SQL module + # will print a message (only in debugging mode), and will + # return "noop". + # + # You can ignore these packets by uncommenting the following + # three lines. Otherwise, the server will not respond to the + # accounting request, and the NAS will retransmit. + # +# if (noop) { +# ok +# } + + # Cisco VoIP specific bulk accounting +# pgsql-voip + + # For Exec-Program and Exec-Program-Wait + exec + + # Filter attributes from the accounting response. + attr_filter.accounting_response + + # + # See "Autz-Type Status-Server" for how this works. + # +# Acct-Type Status-Server { +# +# } +} + + +# Session database, used for checking Simultaneous-Use. Either the radutmp rlm_sql module can handle this. +# The rlm_sql module is *much* faster +session { +# radutmp + + # See "Simultaneous Use Checking Queries" in mods-available/sql + sql +} + + +# Post-Authentication +# Once we KNOW that the user has been authenticated, there are +# additional steps we can take. +post-auth { + # + # If you need to have a State attribute, you can + # add it here. e.g. for later CoA-Request with + # State, and Service-Type = Authorize-Only. + # +# if (!&reply:State) { +# update reply { +# State := "0x%{randstr:16h}" +# } +# } + + # + # Reject packets where User-Name != TLS-Client-Cert-Common-Name + # There is no reason for users to lie about their names. + # + # In general, User-Name == EAP Identity == TLS-Client-Cert-Common-Name + # +# verify_tls_client_common_name + + # + # If there is no Stripped-User-Name in the request, AND we have a client cert, + # then create a Stripped-User-Name from the TLS client certificate information. + # + # Note that this policy MUST be edited for your local system! + # We do not know which fields exist in which certificate, as + # there is no standard here. There is no way for us to have + # a default configuration which "just works" everywhere. We + # can only make recommendations. + # + # The Stripped-User-Name is updated so that it is logged in + # the various "username" fields. This logging means that you + # can associate a particular session with a particular client + # certificate. + # +# if (&EAP-Message && !&Stripped-User-Name && &TLS-Client-Cert-Serial) { +# update request { +# &Stripped-User-Name := "%{%{TLS-Client-Cert-Subject-Alt-Name-Email}:-%{%{TLS-Client-Cert-Common-Name}:-%{TLS-Client-Cert-Serial}}}" +# } +# + # + # Create a Class attribute which is a hash of a bunch + # of information which we hope exists. This + # attribute should be echoed back in + # Accounting-Request packets, which will let the + # administrator correlate authentication and + # accounting. + # +# update reply { +# Class += "%{md5:%{Calling-Station-Id}%{Called-Station-Id}%{TLS-Client-Cert-Subject-Alt-Name-Email}%{TLS-Client-Cert-Common-Name}%{TLS-Client-Cert-Serial}%{NAS-IPv6-Address}%{NAS-IP-Address}%{NAS-Identifier}%{NAS-Port}" +# } +# +# } + + # + # For EAP-TTLS and PEAP, add the cached attributes to the reply. + # The "session-state" attributes are automatically cached when + # an Access-Challenge is sent, and automatically retrieved + # when an Access-Request is received. + # + # The session-state attributes are automatically deleted after + # an Access-Reject or Access-Accept is sent. + # + # If both session-state and reply contain a User-Name attribute, remove + # the one in the reply if it is just a copy of the one in the request, so + # we don't end up with two User-Name attributes. + + if (session-state:User-Name && reply:User-Name && request:User-Name && (reply:User-Name == request:User-Name)) { + update reply { + &User-Name !* ANY + } + } + update { + &reply: += &session-state: + } + + # + # Refresh leases when we see a start or alive. Return an address to + # the IP Pool when we see a stop record. + # + # Ensure that &control:Pool-Name is set to determine which + # pool of IPs are used. +# sqlippool + + + # Create the CUI value and add the attribute to Access-Accept. + # Uncomment the line below if *returning* the CUI. +# cui + + # Create empty accounting session to make simultaneous check more robust. See the accounting queries configuration in + # raddb/mods-config/sql/main/*/queries.conf for details. + # + # The "sql_session_start" policy is defined in raddb/policy.d/accounting. See that file for more details. +# sql_session_start + + # + # If you want to have a log of authentication replies, + # un-comment the following line, and enable the + # 'detail reply_log' module. +# reply_log + + # + # After authenticating the user, do another SQL query. + # + # See "Authentication Logging Queries" in mods-available/sql + -sql + + # + # Un-comment the following if you want to modify the user's object + # in LDAP after a successful login. + # +# ldap + + # For Exec-Program and Exec-Program-Wait + exec + + # + # In order to calcualate the various keys for old style WiMAX + # (non LTE) you will need to define the WiMAX NAI, usually via + # + # update request { + # &WiMAX-MN-NAI = "%{User-Name}" + # } + # + # If you want various keys to be calculated, you will need to + # update the reply with "template" values. The module will see + # this, and replace the template values with the correct ones + # taken from the cryptographic calculations. e.g. + # + # update reply { + # &WiMAX-FA-RK-Key = 0x00 + # &WiMAX-MSK = "%{reply:EAP-MSK}" + # } + # + # You may want to delete the MS-MPPE-*-Keys from the reply, + # as some WiMAX clients behave badly when those attributes + # are included. See "raddb/modules/wimax", configuration + # entry "delete_mppe_keys" for more information. + # + # For LTE style WiMAX you need to populate the following with the + # relevant values: + # control:WiMAX-SIM-Ki + # control:WiMAX-SIM-OPc + # control:WiMAX-SIM-AMF + # control:WiMAX-SIM-SQN + # +# wimax + + # If there is a client certificate (EAP-TLS, sometimes PEAP + # and TTLS), then some attributes are filled out after the + # certificate verification has been performed. These fields + # MAY be available during the authentication, or they may be + # available only in the "post-auth" section. + # + # The first set of attributes contains information about the + # issuing certificate which is being used. The second + # contains information about the client certificate (if + # available). +# +# update reply { +# Reply-Message += "%{TLS-Cert-Serial}" +# Reply-Message += "%{TLS-Cert-Expiration}" +# Reply-Message += "%{TLS-Cert-Subject}" +# Reply-Message += "%{TLS-Cert-Issuer}" +# Reply-Message += "%{TLS-Cert-Common-Name}" +# Reply-Message += "%{TLS-Cert-Subject-Alt-Name-Email}" +# +# Reply-Message += "%{TLS-Client-Cert-Serial}" +# Reply-Message += "%{TLS-Client-Cert-Expiration}" +# Reply-Message += "%{TLS-Client-Cert-Subject}" +# Reply-Message += "%{TLS-Client-Cert-Issuer}" +# Reply-Message += "%{TLS-Client-Cert-Common-Name}" +# Reply-Message += "%{TLS-Client-Cert-Subject-Alt-Name-Email}" +# } + + # Insert class attribute (with unique value) into response, + # aids matching auth and acct records, and protects against duplicate + # Acct-Session-Id. Note: Only works if the NAS has implemented + # RFC 2865 behaviour for the class attribute, AND if the NAS + # supports long Class attributes. Many older or cheap NASes + # only support 16-octet Class attributes. +# insert_acct_class + + # MacSEC requires the use of EAP-Key-Name. However, we don't + # want to send it for all EAP sessions. Therefore, the EAP + # modules put required data into the EAP-Session-Id attribute. + # This attribute is never put into a request or reply packet. + # + # Uncomment the next few lines to copy the required data into + # the EAP-Key-Name attribute +# if (&reply:EAP-Session-Id) { +# update reply { +# EAP-Key-Name := &reply:EAP-Session-Id +# } +# } + + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + + # + # Access-Reject packets are sent through the REJECT sub-section of the + # post-auth section. + # + # Add the ldap module name (or instance) if you have set + # 'edir = yes' in the ldap module configuration + # + # The "session-state" attributes are not available here. + # + Post-Auth-Type REJECT { + # log failed authentications in SQL, too. + -sql + attr_filter.access_reject + + # Insert EAP-Failure message if the request was rejected by policy instead of because of an authentication failure + eap + + # Remove reply message if the response contains an EAP-Message + remove_reply_message_if_eap + } + + # Filter access challenges. + # + Post-Auth-Type Challenge { +# remove_reply_message_if_eap +# attr_filter.access_challenge.post-auth + } + + # + # The Client-Lost section will be run for a request when + # FreeRADIUS has given up waiting for an end-users client to + # respond. This is most useful for logging EAP sessions where + # the client stopped responding (likely because the + # certificate was not acceptable.) i.e. this is not for + # RADIUS clients, but for end-user systems. + # + # This will only be triggered by new packets arriving, + # and will be run at some point in the future *after* the + # original request has been discarded. + # + # Therefore the *ONLY* attributes that are available here + # are those in the session-state list. If you want data + # to log, make sure it is copied to &session-state: + # before the client stops responding. NONE of the other + # original attributes (request, reply, etc) will be + # available. + # + # This section will only be run if `postauth_client_lost` + # is enabled in the main configuration in `radiusd.conf`. + # + # Note that there are MANY reasons why an end users system + # might not respond: + # + # * it could not get the packet due to firewall issues + # * it could not get the packet due to a lossy network + # * the users system might not like the servers cert + # * the users system might not like something else... + # + # In some cases, the client is helpful enough to send us a + # TLS Alert message, saying what it doesn't like about the + # certificate. In other cases, no such message is available. + # + # All that we can know on the FreeRADIUS side is that we sent + # an Access-Challenge, and the client never sent anything + # else. The reasons WHY this happens are buried inside of + # the logs on the client system. No amount of looking at the + # FreeRADIUS logs, or poking the FreeRADIUS configuration + # will tell you why the client gave up. The answers are in + # the logs on the client side. And no, the FreeRADIUS team + # didn't write the client, so we don't know where those logs + # are, or how to get at them. + # + # Information about the TLS state changes is in the + # &session-state:TLS-Session-Information attribute. + # + Post-Auth-Type Client-Lost { + # + # Debug ALL of the TLS state changes done during the + # EAP negotiation. + # +# %{debug_attr:&session-state:TLS-Session-Information[*]} + + # + # Debug the LAST TLS state change done during the EAP + # negotiation. For errors, this is usually a TLS + # alert from the client saying something like + # "unknown CA". + # +# %{debug_attr:&session-state:TLS-Session-Information[n]} + + # + # Debug the last module failure message. This may be + # useful, or it may refer to a server-side failure + # which did not cause the client to stop talking to the server. + # +# %{debug_attr:&session-state:Module-Failure-Message} + } + + # + # If the client sends EAP-Key-Name in the request, + # then echo the real value back in the reply. + # + if (EAP-Key-Name && &reply:EAP-Session-Id) { + update reply { + &EAP-Key-Name := &reply:EAP-Session-Id + } + } +} + +# +# When the server decides to proxy a request to a home server, +# the proxied request is first passed through the pre-proxy +# stage. This stage can re-write the request, or decide to +# cancel the proxy. +# +# Only a few modules currently have this method. +# +pre-proxy { + # Before proxing the request add an Operator-Name attribute identifying + # if the operator-name is found for this client. + # No need to uncomment this if you have already enabled this in + # the authorize section. +# operator-name + + # The client requests the CUI by sending a CUI attribute + # containing one zero byte. + # Uncomment the line below if *requesting* the CUI. +# cui + + # Uncomment the following line if you want to change attributes + # as defined in the preproxy_users file. +# files + + # Uncomment the following line if you want to filter requests + # sent to remote servers based on the rules defined in the + # 'attrs.pre-proxy' file. +# attr_filter.pre-proxy + + # If you want to have a log of packets proxied to a home + # server, un-comment the following line, and the + # 'detail pre_proxy_log' section, above. +# pre_proxy_log +} + +# +# When the server receives a reply to a request it proxied +# to a home server, the request may be massaged here, in the +# post-proxy stage. +# +post-proxy { + + # If you want to have a log of replies from a home server, + # un-comment the following line, and the 'detail post_proxy_log' + # section, above. +# post_proxy_log + + # Uncomment the following line if you want to filter replies from + # remote proxies based on the rules defined in the 'attrs' file. +# attr_filter.post-proxy + + # + # If you are proxying LEAP, you MUST configure the EAP + # module, and you MUST list it here, in the post-proxy + # stage. + # + # You MUST also use the 'nostrip' option in the 'realm' + # configuration. Otherwise, the User-Name attribute + # in the proxied request will not match the user name + # hidden inside of the EAP packet, and the end server will + # reject the EAP request. + # + eap + + # + # If the server tries to proxy a request and fails, then the + # request is processed through the modules in this section. + # + # The main use of this section is to permit robust proxying + # of accounting packets. The server can be configured to + # proxy accounting packets as part of normal processing. + # Then, if the home server goes down, accounting packets can + # be logged to a local "detail" file, for processing with + # radrelay. When the home server comes back up, radrelay + # will read the detail file, and send the packets to the + # home server. + # + # See the "mods-available/detail.example.com" file for more + # details on writing a detail file specifically for one + # destination. + # + # See the "sites-available/robust-proxy-accounting" virtual + # server for more details on reading this "detail" file. + # + # With this configuration, the server always responds to + # Accounting-Requests from the NAS, but only writes + # accounting packets to disk if the home server is down. + # +# Post-Proxy-Type Fail-Accounting { +# detail.example.com +# } +} +} \ No newline at end of file diff --git a/files/sites-available/dhcp b/files/sites-available/dhcp new file mode 100644 index 0000000..f8f8416 --- /dev/null +++ b/files/sites-available/dhcp @@ -0,0 +1,595 @@ +# -*- text -*- +###################################################################### +# +# This is a virtual server that handles DHCP. +# +# See raddb/mods-available/dhcp_sqlippool for the IP Pool configuration. +# +# See raddb/policy.d/dhcp_sqlippool for the "glue" code that allows +# the RADIUS based "sqlippool" module to be used for DHCP. +# +# See raddb/mods-config/sql/ippool/ for the schemas. +# +# See raddb/sites-available/dhcp for instructions on how to configure +# the DHCP server. +# +# $Id$ +# +###################################################################### + +# +# The DHCP functionality goes into a virtual server. +# +server dhcp { + +# Define a DHCP socket. +# +# The default port below is 6700, so you don't break your network. +# If you want it to do real DHCP, change this to 67, and good luck! +# +# You can also bind the DHCP socket to an interface. +# See below, and raddb/radiusd.conf for examples. +# +# This lets you run *one* DHCP server instance and have it listen on +# multiple interfaces, each with a separate policy. +# +# If you have multiple interfaces, it is a good idea to bind the +# listen section to an interface. You will also need one listen +# section per interface. +# +# FreeBSD does *not* support binding sockets to interfaces. Therefore, +# if you have multiple interfaces, broadcasts may go out of the wrong +# one, or even all interfaces. The solution is to use the "setfib" command. +# If you have a network "10.10.0/24" on LAN1, you will need to do: +# +# Pick any IP on the 10.10.0/24 network +# $ setfib 1 route add default 10.10.0.1 +# +# Edit /etc/rc.local, and add a line: +# setfib 1 /path/to/radiusd +# +# The kern must be built with the following options: +# options ROUTETABLES=2 +# or any value larger than 2. +# +# The other only solution is to update FreeRADIUS to use BPF sockets. +# +listen { + # This is a dhcp socket. + type = dhcp + + # IP address to listen on. Will usually be the IP of the + # interface, or 0.0.0.0 + ipaddr = 0.0.0.0 + + # source IP address for unicast packets sent by the + # DHCP server. + # + # The source IP for unicast packets is chosen from the first + # one of the following items which returns a valid IP + # address: + # + # src_ipaddr + # ipaddr + # reply:DHCP-Server-IP-Address + # reply:DHCP-DHCP-Server-Identifier + # + src_ipaddr = 127.0.0.1 + + # The port should be 67 for a production network. Don't set + # it to 67 on a production network unless you really know + # what you're doing. Even if nothing is configured below, the + # server may still NAK legitimate responses from clients. + port = 6700 + + # Interface name we are listening on. See comments above. +# interface = lo0 + + # The DHCP server defaults to allowing broadcast packets. + # Set this to "no" only when the server receives *all* packets + # from a relay agent. i.e. when *no* clients are on the same + # LAN as the DHCP server. + # + # It's set to "no" here for testing. It will usually want to + # be "yes" in production, unless you are only dealing with + # relayed packets. + broadcast = no + + # On Linux if you're running the server as non-root, you + # will need to do: + # + # setcap cap_net_admin,cap_net_bind_service=eip /path/to/radiusd + # + # This will allow the server to set ARP table entries + # for newly allocated IPs, when run as the "radius" user. + # + # The above "setcap" command adds the capability to the program, + # usually so long as it is run by the "radius" user. Which means + # (oddly enough) that it no longer works when run as root! + # + # When running the server as root in debug mode, you can use: + # + # capsh --caps="cap_setpcap,cap_setuid,cap_setgid,cap_net_admin,cap_net_bind_service+eip" --keep=1 --user=radius --addamb=cap_net_admin,cap_net_bind_service -- -c "/path/to/radiusd -X" + # + # Or, simply "sudo" or "su" to the "radius" user, and then run + # the server in debug mode. + + # De-duplicate DHCP packets. If clients don't receive + # a reply within their timeout, most will re-transmit. + # A reply to either packet will satisfy, so de-duplicating + # helps manage load on a busy server + performance { + skip_duplicate_checks = no + } +} + +# Packets received on the socket will be processed through one +# of the following sections, named after the DHCP packet type. +# See dictionary.dhcp for the packet types. + +# Return packets will be sent to, in preference order: +# DHCP-Gateway-IP-Address +# DHCP-Client-IP-Address +# DHCP-Your-IP-Address +# At least one of these attributes should be set at the end of each +# section for a response to be sent. + +# An internal attribute of DHCP-Network-Subnet is set to provide +# a basis for determining the network that a client belongs to. This +# is a hierarchical assignment based on: +# +# - DHCP-Relay-Link-Selection +# - DHCP-Subnet-Selection-Option +# - DHCP-Gateway-IP-Address +# - DHCP-Client-IP-Address +# +# Except for cases where all IP allocation is performed using a mapping from +# the device MAC address to a fixed IP address the DHCP configuration will +# involve the use of one or more pools. +# +# Each pool should be composed of a set of equally valid IP addresses for the +# devices designated as users of the pool. During IP allocation the choice of +# pool is driven by setting the Pool-Name attribute which may either be +# specified directly or chosen (usually with the help of the dhcp_network +# module) based on the initial value of DHCP-Network-Subnet. +# +# DHCP-Network-Subnet indicates the network from which the request is +# originating. In cases where the originating network alone is insufficent to +# define the required IP allocated policy, DHCP-Network-Subnet may be +# overridden to force the selection of a particular pool. +# +# IP addresses belonging to a single pool that is designated for a Layer 2 +# network containing multiple subnets (a "shared-network" or "multinet" +# configuration as defined by some other DHCP servers), will by definition be +# members of distinct subnets that require their own DHCP reply parameters. In +# this case the dhcp_subnet policy can be used to set the correct +# DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address options +# based on the allocated IP. + +dhcp DHCP-Discover { + + # The DHCP Server Identifier is set here since is returned in OFFERs + update control { + &DHCP-DHCP-Server-Identifier = 192.0.2.2 + } + + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # If clients need to be assigned to a particular network based on + # an attribute in the packet rather than the calculated + # DHCP-Network-Subnet described above, then call a policy + # (defined in policy.d/dhcp) to perform the override + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Do a simple mapping of MAC to assigned IP. + # + # See below for the definition of the "mac2ip" + # module. + # + #mac2ip + + # Or, allocate IPs from the DHCP pool in SQL. You may need to + # set the pool name here if you haven't set it elsewhere. + #update control { + # &Pool-Name := "local" + #} + #dhcp_sqlippool + + # If the IP address was not allocated, do something else. + # You could call a Perl, Python, or Java script here. + #if (notfound) { + # ... + #} + + # "Shared-networks" may have multiple IP subnets co-existing in a + # single Layer 2 network. If the pool for the network contains + # addresses from more that one subnet then the setting subnet-specific + # DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address + # parameters must be performed after the allocation of the IP address. + # + # Set any subnet-specific parameters using this policy. + # + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this. + # + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # As an alternative or complement to configuration files based lookup + # for options data you can instead use an SQL database. Example + # configuration is found in dhcp_policy_sql in policy.d/dhcp which + # will need to be adapted to your requirements. + #dhcp_policy_sql + + # Set the type of packet to send in reply. + # + # The server will look at the DHCP-Message-Type attribute to + # determine which type of packet to send in reply. Common + # values would be DHCP-Offer, DHCP-Ack or DHCP-NAK. See + # dictionary.dhcp for all the possible values. + # + # DHCP-Do-Not-Respond can be used to tell the server to not + # respond. + # + # In the event that DHCP-Message-Type is not set then the + # server will fall back to determining the type of reply + # based on the rcode of this section. + # + #update reply { + # DHCP-Message-Type = DHCP-Offer + #} + # + # If DHCP-Message-Type is not set, returning "ok" or + # "updated" from this section will respond with a DHCP-Offer + # message. + # + # Other rcodes will tell the server to not return any response. + # + #ok +} + +dhcp DHCP-Request { + + # You must set the DHCP Server Identifier here since this is returned + # in ACKs and is used to determine whether a request containing a + # "server-ip" field is intended for this server + update control { + &DHCP-DHCP-Server-Identifier = 192.0.2.2 + } + + # If the request is not for this server then silently discard it + if (&request:DHCP-DHCP-Server-Identifier && \ + &request:DHCP-DHCP-Server-Identifier != &control:DHCP-DHCP-Server-Identifier) { + do_not_respond + } + + # Response packet type. See DHCP-Discover section above. + #update reply { + # &DHCP-Message-Type = DHCP-Ack + #} + + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Do a simple mapping of MAC to assigned IP. + # + # See below for the definition of the "mac2ip" + # module. + # + #mac2ip + + # Or, allocate IPs from the DHCP pool in SQL. You may need to + # set the pool name here if you haven't set it elsewhere. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_request + + # If the IP was not allocated, do something else. + # You could call a Perl, Python, or Java script here. + #if (notfound) { + # ... + #} + + # "Shared-networks" may have multiple IP subnets co-existing in a + # single Layer 2 network. If the pool for the network contains + # addresses from more that one subnet then the setting subnet-specific + # DHCP-Subnet-Mask, DHCP-Router-Address and DHCP-Broadcast-Address + # parameters must be performed after the allocation of the IP address. + # + # Set any subnet-specific parameters using this policy. + # + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # As an alternative or complement to configuration files based lookup + # for options data you can instead use an SQL database. Example + # configuration is found in dhcp_policy_sql in policy.d/dhcp which + # will need to be adapted to your requirements. + #dhcp_policy_sql + + # If DHCP-Message-Type is not set, returning "ok" or + # "updated" from this section will respond with a DHCP-Ack + # packet. + # + # "handled" will not return a packet, all other rcodes will + # send back a DHCP-NAK. + # + #ok +} + +# +# Other DHCP packet types +# +# There should be a separate section for each DHCP message type. +# By default this configuration will ignore them all. Any packet type +# not defined here will be responded to with a DHCP-NAK. + +dhcp DHCP-Decline { + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple networks use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Use a policy that set options from data stored in an SQL database + #dhcp_policy_sql + + # If using IPs from a DHCP pool in SQL then you may need to set the + # pool name here if you haven't set it elsewhere and release the IP. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_decline + + update reply { + &DHCP-Message-Type = DHCP-Do-Not-Respond + } + reject +} + +# +# A dummy config for Inform packets - this should match the +# options set in the Request section above, except Inform replies +# must not set Your-IP-Address or IP-Address-Lease-Time +# +dhcp DHCP-Inform { + # Call a policy (defined in policy.d/dhcp) to set common reply attributes + dhcp_common + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and network options + # For multiple networks use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # Use a policy with calls a "files" module of the same name to lookup + # subnet options + # Enable mods-available/dhcp_files AND uncomment dhcp_subnet in + # policy.d/dhcp to use this + # Options are set in mods-config/files/dhcp + #dhcp_subnet + + # Use a "files" module to lookup options based on DHCP-Group-Name + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_group_options + + # Use a "files" module to lookup host specific options + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_hosts + + # Use a policy that set options from data stored in an SQL database + #dhcp_policy_sql + + ok +} + +# +# For Windows 7 boxes +# +#dhcp DHCP-Inform { +# update reply { +# Packet-Dst-Port = 67 +# DHCP-Message-Type = DHCP-ACK +# DHCP-DHCP-Server-Identifier = "%{Packet-Dst-IP-Address}" +# DHCP-Site-specific-28 = 0x0a00 +# } +# ok +#} + +dhcp DHCP-Release { + + # Use a "passwd" module to set group memberships in DHCP-Group-Name + # Enable mods-available/dhcp_passwd to use this + #dhcp_group_membership + + # Optionally override the network address based on client attributes + # See Discover section + #dhcp_override_network + + # Use a "files" module to lookup global and subnet options + # For multiple subnets use this in place of dhcp_common + # Enable mods-available/dhcp_files to use this + # Options are set in mods-config/files/dhcp + #dhcp_network + + # If using IPs from a DHCP pool in SQL then you may need to set the + # pool name here if you haven't set it elsewhere and release the IP. +# update control { +# &Pool-Name := "local" +# } +# dhcp_sqlippool_release + + update reply { + &DHCP-Message-Type = DHCP-Do-Not-Respond + } + reject +} + + +dhcp DHCP-Lease-Query { + # The thing being queried for is implicit + # in the packets. + + # has MAC, asking for IP, etc. + if (&DHCP-Client-Hardware-Address) { + # look up MAC in database + } + + # has IP, asking for MAC, etc. + elsif (&DHCP-Your-IP-Address) { + # look up IP in database + } + + # has host name, asking for IP, MAC, etc. + elsif (&DHCP-Client-Identifier) { + # look up identifier in database + } + else { + update reply { + &DHCP-Message-Type = DHCP-Lease-Unknown + } + + ok + + # stop processing + return + } + + # + # We presume that the database lookup returns "notfound" + # if it can't find anything. + # + if (notfound) { + update reply { + &DHCP-Message-Type = DHCP-Lease-Unknown + } + ok + return + } + + # + # Add more logic here. Is the lease inactive? + # If so, respond with DHCP-Lease-Unassigned. + # + # Otherwise, respond with DHCP-Lease-Active + # + + # + # Also be sure to return ALL information about + # the lease. + # + + # + # The reply types are: + # + # DHCP-Lease-Unknown + # DHCP-Lease-Active + # DHCP-Lease-Unassigned + # + update reply { + &DHCP-Message-Type = DHCP-Lease-Unassigned + } + +} + +} + +###################################################################### +# +# This next section is a sample configuration for the "passwd" +# module, that reads flat-text files. It should go into +# radiusd.conf, in the "modules" section. +# +# The file is in the format , +# +# 00:01:02:03:04:05,192.0.2.100 +# 01:01:02:03:04:05,192.0.2.101 +# 02:01:02:03:04:05,192.0.2.102 +# +# This lets you perform simple static IP assignment. +# +# There is a preconfigured "mac2ip" module setup in +# mods-available/mac2ip. To use it do: +# +# # cd raddb/ +# # ln -s ../mods-available/mac2ip mods-enabled/mac2ip +# # mkdir mods-config/passwd +# +# Then create the file mods-config/passwd/mac2ip with the above +# format. +# +###################################################################### + + +# This is an example only - see mods-available/mac2ip instead; do +# not uncomment these lines here. +# +#passwd mac2ip { +# filename = ${confdir}/mac2ip +# format = "*DHCP-Client-Hardware-Address:=DHCP-Your-IP-Address" +# delimiter = "," +#} \ No newline at end of file diff --git a/files/sites-available/inner-tunnel b/files/sites-available/inner-tunnel new file mode 100644 index 0000000..918cd35 --- /dev/null +++ b/files/sites-available/inner-tunnel @@ -0,0 +1,126 @@ +###################################################################### +# +# This is a virtual server that handles *only* inner tunnel +# requests for EAP-TTLS and PEAP types. +# +###################################################################### + +server inner-tunnel { + + listen { + ipaddr = 127.0.0.1 + port = 18120 + type = auth + } + + authorize { + filter_username + # filter_inner_identity + chap + mschap + # unix + # IPASS + suffix + # ntdomain + + update control { + &Proxy-To-Realm := LOCAL + } + + eap { + ok = return + } + + files + -sql + # smbpasswd + -ldap + # daily + expiration + logintime + pap + } + + authenticate { + Auth-Type PAP { + pap + } + + Auth-Type CHAP { + chap + } + + Auth-Type MS-CHAP { + mschap + } + + mschap + # pam + + # Auth-Type LDAP { + # ldap + # } + + eap + } + + session { + radutmp + # sql + } + + # Post-Authentication + post-auth { + # cui-inner + + # update outer.session-state { + # User-Name := &User-Name + # } + + # reply_log + -sql + # ldap + # moonshot_host_tid + # moonshot_realm_tid + # moonshot_coi_tid + + if (0) { + update reply { + User-Name !* ANY + Message-Authenticator !* ANY + EAP-Message !* ANY + Proxy-State !* ANY + MS-MPPE-Encryption-Types !* ANY + MS-MPPE-Encryption-Policy !* ANY + MS-MPPE-Send-Key !* ANY + MS-MPPE-Recv-Key !* ANY + } + + update { + &outer.session-state: += &reply: + } + } + + Post-Auth-Type REJECT { + -sql + attr_filter.access_reject + + update outer.session-state { + &Module-Failure-Message := &request:Module-Failure-Message + } + } + } + + pre-proxy { + # files + # attr_filter.pre-proxy + # pre_proxy_log + } + + post-proxy { + # post_proxy_log + # attr_filter.post-proxy + eap + } + +} # inner-tunnel server block \ No newline at end of file diff --git a/files/sites-available/status b/files/sites-available/status new file mode 100644 index 0000000..74c322d --- /dev/null +++ b/files/sites-available/status @@ -0,0 +1,126 @@ +# -*- text -*- +###################################################################### +# +# A virtual server to handle ONLY Status-Server packets. +# +# Server statistics can be queried with a properly formatted +# Status-Server request. See dictionary.freeradius for comments. +# +# If radiusd.conf has "status_server = yes", then any client +# will be able to send a Status-Server packet to any port +# (listen section type "auth", "acct", or "status"), and the +# server will respond. +# +# If radiusd.conf has "status_server = no", then the server will +# ignore Status-Server packets to "auth" and "acct" ports. It +# will respond only if the Status-Server packet is sent to a +# "status" port. +# +# The server statistics are available ONLY on socket of type +# "status". Queries for statistics sent to any other port +# are ignored. +# +# Similarly, a socket of type "status" will not process +# authentication or accounting packets. This is for security. +# +# $Id: e7d4346310b837d56bffe4c991b4e5680742ebc0 $ +# +###################################################################### + +server status { + listen { + # ONLY Status-Server is allowed to this port. + # ALL other packets are ignored. + type = status + + ipaddr = $ENV{FREERADIUS_SITES_STATUS_LISTEN} + port = $ENV{FREERADIUS_SITES_STATUS_PORT} + } + + # + # We recommend that you list ONLY management clients here. + # i.e. NOT your NASes or Access Points, and for an ISP, + # DEFINITELY not any RADIUS servers that are proxying packets + # to you. + # + # If you do NOT list a client here, then any client that is + # globally defined (i.e. all of them) will be able to query + # these statistics. + # + # Do you really want your partners seeing the internal details + # of what your RADIUS server is doing? + # + client admin { + ipaddr = 127.0.0.1 + secret = $ENV{FREERADIUS_SITES_STATUS_SECRET} + } + + # Simple authorize section. The "Autz-Type Status-Server" + # section will work here, too. See "raddb/sites-available/default". + authorize { + ok + + # respond to the Status-Server request. + Autz-Type Status-Server { + ok + } + } +} + +# Statistics can be queried via a number of methods: +# +# All packets received/sent by the server (1 = auth, 2 = acct) +# FreeRADIUS-Statistics-Type = 3 +# +# All packets proxied by the server (4 = proxy-auth, 8 = proxy-acct) +# FreeRADIUS-Statistics-Type = 12 +# +# All packets sent && received: +# FreeRADIUS-Statistics-Type = 15 +# +# Internal server statistics: +# FreeRADIUS-Statistics-Type = 16 +# +# All packets for a particular client (globally defined) +# FreeRADIUS-Statistics-Type = 35 +# FreeRADIUS-Stats-Client-IP-Address = 192.0.2.1 +# +# All packets for a client attached to a "listen" ip/port +# FreeRADIUS-Statistics-Type = 35 +# FreeRADIUS-Stats-Client-IP-Address = 192.0.2.1 +# FreeRADIUS-Stats-Server-IP-Address = 127.0.0.1 +# FreeRADIUS-Stats-Server-Port = 1812 +# +# All packets for a "listen" IP/port +# FreeRADIUS-Statistics-Type = 67 +# FreeRADIUS-Stats-Server-IP-Address = 127.0.0.1 +# FreeRADIUS-Stats-Server-Port = 1812 +# +# All packets for a home server IP / port +# FreeRADIUS-Statistics-Type = 131 +# FreeRADIUS-Stats-Server-IP-Address = 192.0.2.2 +# FreeRADIUS-Stats-Server-Port = 1812 + +# +# You can also get exponentially weighted moving averages of +# response times (in usec) of home servers. Just set the config +# item "historic_average_window" in a home_server section. +# +# By default it is zero (don't calculate it). Useful values +# are between 100, and 10,000. The server will calculate and +# remember the moving average for this window, and for 10 times +# that window. +# + +# +# Some of this could have been simplified. e.g. the proxy-auth and +# proxy-acct bits aren't completely necessary. But using them permits +# the server to be queried for ALL inbound && outbound packets at once. +# This gives a good snapshot of what the server is doing. +# +# Due to internal limitations, the statistics might not be exactly up +# to date. Do not expect all of the numbers to add up perfectly. +# The Status-Server packets are also counted in the total requests && +# responses. The responses are counted only AFTER the response has +# been sent. +# diff --git a/files/sites-available/tls b/files/sites-available/tls new file mode 100644 index 0000000..28eb615 --- /dev/null +++ b/files/sites-available/tls @@ -0,0 +1,603 @@ +###################################################################### +# +# RADIUS over TLS (radsec) +# +# When a new client connects, the various TLS parameters for the +# connection are available as dynamic expansions, e.g. +# +# %{listen:TLS-Client-Cert-Common-Name} +# +# Along with other TLS-Client-Cert-... attributes. +# These expansions will only exist if the relevant fields +# are in the client certificate. Read the debug output to see +# which fields are available. Look for output like the following: +# +# (0) TLS - Creating attributes from certificate OIDs +# (0) TLS-Client-Cert-Subject-Alt-Name-Dns := "one.example.org" +# (0) TLS-Client-Cert-Subject-Alt-Name-Dns := "two.example.org" +# ... +# +# It is also possible to distinguish between connections which have +# TLS enables, and ones which do not. The expansion: +# +# %{listen:tls} +# +# Will return "yes" if the connection has TLS enabled. It will +# return "no" if TLS is not enabled for a particular listen section. +# +# A number of TLS-Client-Cert-.. attributes holds X509v3 extensions +# data, attributes named the way OpenSSL names them. It is possible +# to extract data for an extension not known to OpenSSL by defining +# a custom string attribute which contains extension OID in it's +# name after 'TLS-Client-Cert-' prefix. E.g.: +# +# ATTRIBUTE TLS-Client-Cert-1.3.6.1.4.1.311.21.7 3002 string +# +# which will yield something simmilar to: +# +# (0) eap_tls: TLS - Creating attributes from certificate OIDs +# (0) eap_tls: TLS-Client-Cert-1.3.6.1.4.1.311.21.7 += "0x302e06" +# ... +# +###################################################################### + +listen { + + # ipaddr = $ENV{FREERADIUS_SITES_TLS_LISTEN} + ipaddr = * + port = $ENV{FREERADIUS_SITES_TLS_PORT} + + # + # TCP and TLS sockets can accept Access-Request and Accounting-Request on the same socket. + # + # auth = only Access-Request + # acct = only Accounting-Request + # auth+acct = both + # coa = only CoA / Disconnect requests + # + type = auth+acct + + # For now, only TCP transport is allowed. + proto = tcp + + # Send packets to the default virtual server + virtual_server = default + + clients = radsec + + # Use the haproxy "PROXY protocol". + # + # This configuration allows for many FreeRADIUS servers to be behind a haproxy server. The "PROXY protocol" allows haproxy to send the actual client IP to FreeRADIUS. + # + # This will work ONLY for RadSec (TLS). Both the haproxy AND the RadSec client MUST be listed as allowed RADIUS clients. + # + # haproxy needs to have "send-proxy" configured for this server. Health checks should be turned off, as haproxy does not support RADIUS health checks. + # + # The main use of this feature is for scalability. There is no longer any need to have a RADIUS proxy as a load balancer. + # haproxy is fast, stable, and supports dynamic reloads! + # + # The only problem is that many RADIUS clients do not support RadSec. That situation will hopefully change over time. + # +# proxy_protocol = no + + # When this is set to "yes", new TLS connections are processed through a section called + # + # Autz-Type New-TLS-Connection { + # ... + # } + # + # The request contains TLS client certificate attributes, + # and nothing else. The debug output will print which + # attributes are available on your system. + # + # If the section returns "ok" or "updated", then the + # connection is accepted. Otherwise the connection is + # terminated. + # +# check_client_connections = yes + + # + # Connection limiting for sockets with "proto = tcp". + # + limit { + # Limit the number of simultaneous TCP connections to the socket + # + # The default is 16. + # Setting this to 0 means "no limit" + max_connections = 16 + + # The per-socket "max_requests" option does not exist. + + # The lifetime, in seconds, of a TCP connection. After this lifetime, the connection will be closed. + # + # Setting this to 0 means "forever". + lifetime = 0 + + # The idle timeout, in seconds, of a TCP connection. If no packets have been received over the connection for this time, the connection will be closed. + # + # Setting this to 0 means "no timeout". + # We STRONGLY RECOMMEND that you set an idle timeout. + # + idle_timeout = 30 + } + + # This is *exactly* the same configuration as used by the EAP-TLS + # module. It's OK for testing, but for production use it's a good + # idea to use different server certificates for EAP and for RADIUS + # transport. + # + # If you want only one TLS configuration for multiple sockets, + # then we suggest putting "tls { ...}" into radiusd.conf. + # The subsection below can then be changed into a reference: + # + # tls = ${tls} + # + # Which means "the tls sub-section is not here, but instead is in + # the top-level section called 'tls'". + # + # If you have multiple tls configurations, you can put them into + # sub-sections of a top-level "tls" section. There's no need to + # call them all "tls". You can then use: + # + # tls = ${tls.site1} + # + # to refer to the "site1" sub-section of the "tls" section. + # + tls { + private_key_password = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD} + private_key_file = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_FILE} + + # Accept an expired Certificate Revocation List + # allow_expired_crl = no + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below MUST include not + # only the server certificate, but ALSO all + # of the CA certificates used to sign the + # server certificate. + certificate_file = $ENV{FREERADIUS_SITES_TLS_CERTIFICATE_FILE} + + + # Trusted Root CA list + # + # ALL of the CA's in this list will be trusted to issue client certificates for authentication. + # + # In general, you should use self-signed certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain *one* CA certificate. + # + # This parameter is used only for EAP-TLS, when you issue client certificates. If you do not use client certificates, and you do not want + # to permit EAP-TLS authentication, then delete this configuration item. + ca_file = $ENV{FREERADIUS_SITES_TLS_CA_FILE} + + # For DH cipher suites to work, you have to run OpenSSL to create the DH file first: + # + # openssl dhparam -out certs/dh 1024 + # + # dh_file = ${certdir}/dh + + # + # If your system doesn't have /dev/urandom, + # you will need to create this file, and + # periodically change its contents. + # + # For security reasons, FreeRADIUS doesn't + # write to files in its configuration + # directory. + # + # random_file = /dev/urandom + + # + # The default fragment size is 1K. + # However, it's possible to send much more data than + # that over a TCP connection. The upper limit is 64K. + # Setting the fragment size to more than 1K means that + # there are fewer round trips when setting up a TLS + # connection. But only if the certificates are large. + # + fragment_size = 8192 + + # include_length is a flag which is + # by default set to yes If set to + # yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the + # message is included ONLY in the + # First packet of a fragment series. + # + # include_length = yes + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash '. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the line below. + # 5) Restart radiusd + # check_crl = yes + ca_path = ${cadir} + + # OpenSSL does not reload contents of ca_path dir over time. + # That means that if check_crl is enabled and CRLs are loaded + # from ca_path dir, at some point CRLs will expire and + # RADIUSd will stop authenticating NASes. + # If ca_path_reload_interval is non-zero, it will force OpenSSL + # to reload all data from ca_path periodically + # + # Flush ca_path each hour + ca_path_reload_interval = 3600 + + # + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # This check can be done more generally by checking + # the value of the TLS-Client-Cert-Issuer attribute. + # This check can be done via any mechanism you choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Common-Name attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_cn = %{User-Name} + # + # Set this option to specify the allowed + # TLS cipher suites. The format is listed + # in "man 1 ciphers". + cipher_list = $ENV{FREERADIUS_SITES_TLS_CIPHER} + + # If enabled, OpenSSL will use server cipher list + # (possibly defined by cipher_list option above) + # for choosing right cipher suite rather than + # using client-specified list which is OpenSSl default + # behavior. Having it set to yes is a current best practice + # for TLS + cipher_server_preference = no + + # + # Older TLS versions are deprecated. But for RadSec, + # we CAN allow TLS 1.3. + # + tls_min_version = "1.2" + tls_max_version = "1.3" + + # + # Session resumption / fast reauthentication cache. + # + # The cache contains the following information: + # + # session Id - unique identifier, managed by SSL + # User-Name - from the Access-Accept + # Stripped-User-Name - from the Access-Request + # Cached-Session-Policy - from the Access-Accept + # + # The "Cached-Session-Policy" is the name of a + # policy which should be applied to the cached + # session. This policy can be used to assign + # VLANs, IP addresses, etc. It serves as a useful + # way to re-apply the policy from the original + # Access-Accept to the subsequent Access-Accept + # for the cached session. + # + # On session resumption, these attributes are + # copied from the cache, and placed into the + # reply list. + # + # You probably also want "use_tunneled_reply = yes" when using fast session resumption. + # + cache { + # + # Enable it. The default is "no". + # Deleting the entire "cache" subsection + # Also disables caching. + # + # + # As of version 3.0.14, the session cache requires the use + # of the "name" and "persist_dir" configuration items, below. + # + # The internal OpenSSL session cache has been permanently + # disabled. + # + # You can disallow resumption for a + # particular user by adding the following + # attribute to the control item list: + # + # Allow-Session-Resumption = No + # + # If "enable = no" below, you CANNOT + # enable resumption for just one user + # by setting the above attribute to "yes". + # + enable = no + + # + # Lifetime of the cached entries, in hours. + # The sessions will be deleted after this + # time. + # + lifetime = 24 # hours + + # + # Internal "name" of the session cache. + # Used to distinguish which TLS context + # sessions belong to. + # + # The server will generate a random value + # if unset. This will change across server + # restart so you MUST set the "name" if you + # want to persist sessions (see below). + # + # If you use IPv6, change the "ipaddr" below + # to "ipv6addr" + # + #name = "TLS ${..ipaddr} ${..port} ${..proto}" + + # + # Simple directory-based storage of sessions. + # Two files per session will be written, the SSL + # state and the cached VPs. This will persist session + # across server restarts. + # + # The server will need write perms, and the directory + # should be secured from anyone else. You might want + # a script to remove old files from here periodically: + # + # find ${logdir}/tlscache -mtime +2 -exec rm -f {} \; + # + # This feature REQUIRES "name" option be set above. + # + #persist_dir = "${logdir}/tlscache" + } + + # + # Require a client certificate. + # + require_client_cert = yes + + # + # As of version 2.1.10, client certificates can be + # validated via an external command. This allows + # dynamic CRLs or OCSP to be used. + # + # This configuration is commented out in the + # default configuration. Uncomment it, and configure + # the correct paths below to enable it. + # + verify { + # A temporary directory where the client + # certificates are stored. This directory + # MUST be owned by the UID of the server, + # and MUST not be accessible by any other + # users. When the server starts, it will do + # "chmod go-rwx" on the directory, for + # security reasons. The directory MUST + # exist when the server starts. + # + # You should also delete all of the files + # in the directory when the server starts. + # tmpdir = /tmp/radiusd + # tmpdir = /startechnica/freeradius/tmp + + # The command used to verify the client cert. + # We recommend using the OpenSSL command-line + # tool. + # + # The ${..ca_path} text is a reference to + # the ca_path variable defined above. + # + # The %{TLS-Client-Cert-Filename} is the name + # of the temporary file containing the cert + # in PEM format. This file is automatically + # deleted by the server when the command + # returns. + # client = "/path/to/openssl verify -CApath ${..ca_path} %{TLS-Client-Cert-Filename}" + } + } +} + +clients radsec { + client 127.0.0.1 { + ipaddr = 127.0.0.1 + + # Ensure that this client is TLS *only*. + proto = tls + + # TCP clients can have any shared secret. + # TLS clients MUST have the shared secret set to "radsec". Or, for "proto = tls", you can omit the secret, and it will + # automatically be set to "radsec". + # secret = radsec + secret = $ENV{FREERADIUS_CLIENTS_SECRET} + + # You can also use a "limit" section here. + # See raddb/clients.conf for examples. + # + # Note that BOTH limits are applied. You should therefore set the "listen" limits higher than the ones for each individual + # client. + } +} + +# When a request is proxied to a TLS-enabled home server, the TLS parameters are available via the expansion: +# +# %{proxy_listen: ... } +# +# The contents of the expansion are the same as described above with the %{listen: ... } expansion, and have similar meanings. "client" in this case is the proxy (this system) +# and "server" is the remote system (home server). +# +# Note that the %{proxy_listen: ... } parameters are available only AFTER the connection has been made to the home server. +home_server tls { + ipaddr = 127.0.0.1 + port = $ENV{FREERADIUS_SITES_TLS_PORT} + + # type can be the same types as for the "listen" section/ + # e.g. auth, acct, auth+acct, coa + type = auth + secret = radsec + proto = tcp + status_check = none + + tls { + # + # Similarly to HTTP, the client can use Server Name + # Indication to inform the RadSec server of which + # domain it is requesting. This selection allows + # multiple sites to exist at the same IP address. + # + # For example, and identity provider could host + # multiple sites, but present itself with one public + # IP address. + # + # SNI also permits the use of a load balancer such as + # haproxy. That load balancer can terminate the TLS + # connection, and then use SNI to route the + # underlying RADIUS TCP traffic to a particular host. + # + # Note that "hostname" here is only for SNI, and is NOT + # the hostname or IP address we connect to. For that, + # see "ipaddr", above. + # + # hostname = "example.com" + + private_key_password = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD} + # private_key_file = ${certdir}/client.pem + private_key_file = $ENV{FREERADIUS_SITES_TLS_PRIVKEY_FILE} + + # If Private key & Certificate are located in + # the same file, then private_key_file & + # certificate_file must contain the same file + # name. + # + # If ca_file (below) is not used, then the + # certificate_file below MUST include not + # only the server certificate, but ALSO all + # of the CA certificates used to sign the + # server certificate. + # certificate_file = ${certdir}/client.pem + certificate_file = $ENV{FREERADIUS_SITES_TLS_CERTIFICATE_FILE} + + # Trusted Root CA list + # + # ALL of the CA's in this list will be trusted to issue client certificates for authentication. + # + # In general, you should use self-signed certificates for 802.1x (EAP) authentication. + # In that case, this CA file should contain *one* CA certificate. + # + # This parameter is used only for EAP-TLS, + # when you issue client certificates. If you do + # not use client certificates, and you do not want + # to permit EAP-TLS authentication, then delete + # this configuration item. + ca_file = $ENV{FREERADIUS_SITES_TLS_CA_FILE} + + # + # For TLS-PSK, the key should be specified dynamically, instead of using a hard-coded psk_identity and psk_hexphrase. + # + # The input to the dynamic expansion will be the PSK + # identity supplied by the client, in the + # TLS-PSK-Identity attribute. The output of the + # expansion should be a hex string, of no more than + # 512 characters. The string should not be prefixed + # with "0x". e.g. "abcdef" is OK. "0xabcdef" is not. + # + # psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}" + + # For DH cipher suites to work, you have to run OpenSSL to create the DH file first: + # + # openssl dhparam -out certs/dh 1024 + # + dh_file = ${certdir}/dh + random_file = /dev/urandom + + # + # The default fragment size is 1K. + # However, TLS can send 64K of data at once. + # It can be useful to set it higher. + # + fragment_size = 8192 + + # include_length is a flag which is + # by default set to yes If set to + # yes, Total Length of the message is + # included in EVERY packet we send. + # If set to no, Total Length of the + # message is included ONLY in the + # First packet of a fragment series. + # + # include_length = yes + + # Check the Certificate Revocation List + # + # 1) Copy CA certificates and CRLs to same directory. + # 2) Execute 'c_rehash '. + # 'c_rehash' is OpenSSL's command. + # 3) uncomment the line below. + # 5) Restart radiusd + # check_crl = yes + ca_path = ${cadir} + + # + # If check_cert_issuer is set, the value will + # be checked against the DN of the issuer in + # the client certificate. If the values do not + # match, the certificate verification will fail, + # rejecting the user. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Issuer attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd" + + # + # If check_cert_cn is set, the value will + # be xlat'ed and checked against the CN + # in the client certificate. If the values + # do not match, the certificate verification + # will fail rejecting the user. + # + # This check is done only if the previous + # "check_cert_issuer" is not set, or if + # the check succeeds. + # + # In 2.1.10 and later, this check can be done + # more generally by checking the value of the + # TLS-Client-Cert-Common-Name attribute. This check + # can be done via any mechanism you choose. + # + # check_cert_cn = %{User-Name} + # + # Set this option to specify the allowed TLS cipher suites. The format is listed in "man 1 ciphers". + cipher_list = $ENV{FREERADIUS_SITES_TLS_CIPHER} + } + +} + +home_server_pool tls { + type = fail-over + home_server = tls +} + +realm tls { + auth_pool = tls +} \ No newline at end of file diff --git a/index.yaml b/index.yaml new file mode 100644 index 0000000..3e351c1 --- /dev/null +++ b/index.yaml @@ -0,0 +1,115 @@ +apiVersion: v1 +entries: + freeradius: + - annotations: + category: AccessManagement + apiVersion: v2 + appVersion: 3.2.7 + created: "2025-06-16T16:16:37.456715181+02:00" + dependencies: + - name: st-common + repository: https://startechnica.github.io/apps + version: 0.1.12 + - condition: mariadb.enabled + name: mariadb + repository: oci://registry-1.docker.io/bitnamicharts + version: 20.x.x + description: FreeRADIUS is a modular, high performance free RADIUS suite developed + and distributed under the GNU General Public License, version 2, and is free + for download and use. + digest: da3ba6c773298d8e6ff0df4cb8eb2d9effb81e92d4991a74908a136c70457920 + home: https://github.com/startechnica/apps/tree/main/charts/freeradius + icon: https://freeradius.org/img/wordmark.svg + keywords: + - freeradius + - radius + - mysql + - postgresql + - ldap + kubeVersion: '>=1.24.0-0' + maintainers: + - email: firmansyah@nainggolan.id + name: firmansyahn + url: https://firmansyah.nainggolan.id + name: freeradius + sources: + - https://freeradius.org/ + - https://github.com/FreeRADIUS/freeradius-server + type: application + urls: + - freeradius-1.0.3.tgz + version: 1.0.3 + mariadb: + - annotations: + category: Database + images: | + - name: mariadb + image: docker.io/bitnami/mariadb:11.4.7-debian-12-r1 + - name: mysqld-exporter + image: docker.io/bitnami/mysqld-exporter:0.17.2-debian-12-r11 + - name: os-shell + image: docker.io/bitnami/os-shell:12-debian-12-r46 + licenses: Apache-2.0 + tanzuCategory: service + apiVersion: v2 + appVersion: 11.4.7 + created: "2025-06-16T16:16:37.459591908+02:00" + dependencies: + - name: common + repository: oci://registry-1.docker.io/bitnamicharts + tags: + - bitnami-common + version: 2.x.x + description: MariaDB is an open source, community-developed SQL database server + that is widely in use around the world due to its enterprise features, flexibility, + and collaboration with leading tech firms. + digest: 1e5034974b28d6ab585efdaf9a345ea4e4d3024417b680b83f656a4c0b1e2a84 + home: https://bitnami.com + icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/mariadb/img/mariadb-stack-220x234.png + keywords: + - mariadb + - mysql + - database + - sql + - prometheus + maintainers: + - name: Broadcom, Inc. All Rights Reserved. + url: https://github.com/bitnami/charts + name: mariadb + sources: + - https://github.com/bitnami/charts/tree/main/bitnami/mariadb + urls: + - charts/mariadb-20.5.7.tgz + version: 20.5.7 + st-common: + - annotations: + artifacthub.io/changes: | + - kind: added + description: Add dotenv and envvars names helper + category: Infrastructure + apiVersion: v2 + appVersion: 0.1.12 + created: "2025-06-16T16:16:37.460145288+02:00" + description: A Library Helm Chart for grouping common logic between Startechnica + charts. This chart is not deployable by itself. + digest: 4c1c7304cf4dbb900b6fd847cf1d38e6f8d1db46dbf080b4d52c884b84a36747 + home: https://github.com/startechnica/apps/tree/main/charts/common + icon: https://startechnica.github.io/apps/images/star.png + keywords: + - common + - helper + - template + - function + kubeVersion: '>=1.20.0-0' + maintainers: + - email: firmansyah@nainggolan.id + name: firmansyahn + url: https://firmansyah.nainggolan.id + name: st-common + sources: + - https://startechnica.github.io/apps + type: library + urls: + - charts/st-common-0.1.12.tgz + version: 0.1.12 +generated: "2025-06-16T16:16:37.449242718+02:00" diff --git a/packages/freeradius-1.0.3.tgz b/packages/freeradius-1.0.3.tgz new file mode 100644 index 0000000..ab7f158 Binary files /dev/null and b/packages/freeradius-1.0.3.tgz differ diff --git a/templates/Certificate.yaml b/templates/Certificate.yaml new file mode 100644 index 0000000..9a65f83 --- /dev/null +++ b/templates/Certificate.yaml @@ -0,0 +1,54 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "freeradius.createTlsSecret" .) .Values.tls.autoGenerator.certmanager.enabled }} +{{- if not (eq (include "st-common.capabilities.certManager.apiVersion" .) "false") }} +{{- $releaseNamespace := include "st-common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "st-common.names.fullname" . }} +{{- $serviceName := include "st-common.names.fullname" . }} +{{- $altNames := list (printf "%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc" $serviceName $releaseNamespace) (printf "%s.%s" $serviceName $releaseNamespace) $fullname }} +{{/* +{{- $altNames := list (printf "*.%s.%s.svc.%s" $serviceName $releaseNamespace $clusterDomain) (printf "%s.%s.svc" $serviceName $releaseNamespace) (printf "%s.%s" $serviceName $releaseNamespace) $fullname }} +*/}} +apiVersion: {{ include "st-common.capabilities.certManager.apiVersion" . }} +kind: Certificate +metadata: + name: {{ include "st-common.names.fullname" . }}-tls + namespace: {{ include "st-common.names.namespace" . | quote }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} +spec: + secretName: {{ include "freeradius.tlsSecretName" . }} + issuerRef: + group: cert-manager.io + kind: {{ .Values.tls.autoGenerator.certmanager.issuerKind }} + name: {{ .Values.tls.autoGenerator.certmanager.issuerName }} + #name: letsencrypt-prd + privateKey: + algorithm: ECDSA + rotationPolicy: Always + size: 256 + subject: + organizations: + - {{ .Release.Name | quote }} + organizationalUnits: + - {{ include "st-common.names.fullname" . }} + dnsNames: + - {{ .Values.ingress.hostname | quote }} + {{- range .Values.ingress.extraHosts }} + - {{ .name | quote }} + {{- end }} + {{- with $altNames }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} +--- \ No newline at end of file diff --git a/templates/ConfigMap/clients.yaml b/templates/ConfigMap/clients.yaml new file mode 100644 index 0000000..afbe928 --- /dev/null +++ b/templates/ConfigMap/clients.yaml @@ -0,0 +1,23 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if not .Values.clients.existingConfigMapName }} +{{- $client := index .Values "clients" "localhost" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-clients" (include "st-common.names.fullname" .) }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: + clients.conf: |- + client +{{- end }} \ No newline at end of file diff --git a/templates/ConfigMap/envvars.yaml b/templates/ConfigMap/envvars.yaml new file mode 100644 index 0000000..2b6b3a1 --- /dev/null +++ b/templates/ConfigMap/envvars.yaml @@ -0,0 +1,75 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "freeradius.names.envvars" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: + FREERADIUS_ENABLE_TLS: {{ ternary "true" "false" .Values.tls.enabled | quote }} + + FREERADIUS_CLIENTS_SHORTNAME: "" + FREERADIUS_CLIENTS_IPV4ADDR: "" + FREERADIUS_CLIENTS_IPV6ADDR: "" + FREERADIUS_CLIENTS_SECRET: "" + + {{- if .Values.modsEnabled.sql.enabled }} + FREERADIUS_MODS_SQL_DIALECT: {{ .Values.modsEnabled.sql.dialect }} + FREERADIUS_MODS_SQL_SERVER: {{ include "freeradius.database.host" . | quote }} + FREERADIUS_MODS_SQL_PORT: {{ include "freeradius.database.port" . }} + FREERADIUS_MODS_SQL_LOGIN: {{ include "freeradius.database.user" . | quote }} + FREERADIUS_MODS_SQL_DB: {{ include "freeradius.database.name" . | quote }} + FREERADIUS_MODS_SQL_TABLE_ACCT1: {{ .Values.modsEnabled.sql.table.acct1 }} + FREERADIUS_MODS_SQL_TABLE_ACCT2: {{ .Values.modsEnabled.sql.table.acct2 }} + FREERADIUS_MODS_SQL_TABLE_AUTHCHECK: {{ .Values.modsEnabled.sql.table.authcheck }} + FREERADIUS_MODS_SQL_TABLE_AUTHREPLY: {{ .Values.modsEnabled.sql.table.authreply }} + FREERADIUS_MODS_SQL_TABLE_CLIENT: {{ .Values.modsEnabled.sql.table.client }} + FREERADIUS_MODS_SQL_TABLE_GROUPCHECK: {{ .Values.modsEnabled.sql.table.groupcheck }} + FREERADIUS_MODS_SQL_TABLE_GROUPREPLY: {{ .Values.modsEnabled.sql.table.groupreply }} + FREERADIUS_MODS_SQL_TABLE_POSTAUTH: {{ .Values.modsEnabled.sql.table.postauth }} + FREERADIUS_MODS_SQL_TABLE_USERGROUP: {{ .Values.modsEnabled.sql.table.usergroup }} + FREERADIUS_MODS_SQL_TLS_ENABLE: {{ ternary "yes" "no" .Values.modsEnabled.sql.tls.enabled | quote }} + + FREERADIUS_MODS_SQL_READ_CLIENTS: {{ ternary "yes" "no" .Values.modsEnabled.sql.readClients | quote }} + FREERADIUS_MODS_SQL_GROUP_ATTRIBUTE: {{ .Values.modsEnabled.sql.groupAttribute | quote }} + + FREERADIUS_MODS_SQL_SQLITE_FILENAME: {{ .Values.modsEnabled.sql.sqlite.filename | quote }} + FREERADIUS_MODS_SQL_SQLITE_BUSY_TIMEOUT: {{ .Values.modsEnabled.sql.sqlite.busyTimeout | quote }} + + {{- if .Values.modsEnabled.sql.tls.enabled }} + FREERADIUS_MODS_SQL_TLS_CACERT: {{ include "freeradius.sqlTlsCACert" . | quote }} + FREERADIUS_MODS_SQL_TLS_CIPHER: {{ .Values.modsEnabled.sql.tls.ciphers | quote }} + FREERADIUS_MODS_SQL_TLS_CERTIFICATE: {{ include "freeradius.sqlTlsCert" . | quote }} + FREERADIUS_MODS_SQL_TLS_PRIVATEKEY: {{ include "freeradius.sqlTlsCertKey" . | quote }} + FREERADIUS_MODS_SQL_TLS_PRIVATEKEY_PASSWORD: {{ .Values.modsEnabled.sql.tls.privateKeyPassword | quote }} + {{- end }} + {{- end }} + + FREERADIUS_SITES_NAMESPACE: radius + + FREERADIUS_SITES_DEFAULT_AUTH_PORT: {{ .Values.containerPorts.auth | quote }} + FREERADIUS_SITES_DEFAULT_ACCT_PORT: {{ .Values.containerPorts.acct | quote }} + {{- if .Values.sitesEnabled.coa.enabled }} + FREERADIUS_SITES_COA_PORT: {{ .Values.containerPorts.coa | quote }} + {{- end }} + {{- if .Values.sitesEnabled.status.enabled }} + FREERADIUS_SITES_STATUS_LISTEN: {{ .Values.sitesEnabled.status.listen | quote }} + FREERADIUS_SITES_STATUS_PORT: {{ .Values.containerPorts.status | quote }} + {{- end }} + {{- if .Values.sitesEnabled.tls.enabled }} + FREERADIUS_SITES_TLS_PORT: {{ .Values.containerPorts.radsec | quote }} + FREERADIUS_SITES_TLS_CA_FILE: {{ include "freeradius.tlsCACert" . | quote }} + FREERADIUS_SITES_TLS_CERTIFICATE_FILE: {{ include "freeradius.tlsCert" . | quote }} + FREERADIUS_SITES_TLS_CIPHER: {{ default "DEFAULT" .Values.sitesEnabled.tls.cipher | quote }} + FREERADIUS_SITES_TLS_PRIVKEY_FILE: {{ include "freeradius.tlsCertKey" . | quote }} + {{- end }} diff --git a/templates/ConfigMap/mods-enabled.yaml b/templates/ConfigMap/mods-enabled.yaml new file mode 100644 index 0000000..169bc9f --- /dev/null +++ b/templates/ConfigMap/mods-enabled.yaml @@ -0,0 +1,21 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-mods" (include "st-common.names.fullname" .) }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: +{{- if .Values.modsEnabled.sql.enabled }} +{{ (.Files.Glob "files/mods-available/sql").AsConfig | indent 2 }} +{{- end }} diff --git a/templates/ConfigMap/sites-enabled.yaml b/templates/ConfigMap/sites-enabled.yaml new file mode 100644 index 0000000..d751767 --- /dev/null +++ b/templates/ConfigMap/sites-enabled.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +data: +{{ (.Files.Glob "files/sites-available/default").AsConfig | indent 2 }} +{{ (.Files.Glob "files/sites-available/inner-tunnel").AsConfig | indent 2 }} +{{- if .Values.sitesEnabled.coa.enabled }} +{{ (.Files.Glob "files/sites-available/coa").AsConfig | indent 2 }} +{{- end }} +{{- if .Values.sitesEnabled.status.enabled }} +{{ (.Files.Glob "files/sites-available/status").AsConfig | indent 2 }} +{{- end }} +{{- if .Values.sitesEnabled.tls.enabled }} +{{ (.Files.Glob "files/sites-available/tls").AsConfig | indent 2 }} +{{- end }} \ No newline at end of file diff --git a/templates/Deployment.yaml b/templates/Deployment.yaml new file mode 100644 index 0000000..d173b5c --- /dev/null +++ b/templates/Deployment.yaml @@ -0,0 +1,366 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{- $globalSecretName := printf "%s" (tpl (include "st-common.secrets.name" (dict "existingSecret" .Values.auth.existingSecret "context" $)) $) }} +apiVersion: {{ include "st-common.capabilities.deployment.apiVersion" . }} +kind: Deployment +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: {{- include "st-common.labels.matchLabels" . | nindent 6 }} + app.kubernetes.io/component: freeradius + {{- if .Values.updateStrategy }} + strategy: {{- toYaml .Values.updateStrategy | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + checksum/configmap-env: {{ include (print $.Template.BasePath "/ConfigMap/envvars.yaml") . | sha256sum }} + checksum/configmap-mods: {{ include (print $.Template.BasePath "/ConfigMap/mods-enabled.yaml") . | sha256sum }} + checksum/configmap-sites: {{ include (print $.Template.BasePath "/ConfigMap/sites-enabled.yaml") . | sha256sum }} + checksum/secret-credentials: {{ include (print $.Template.BasePath "/Secret/credentials.yaml") . | sha256sum }} + checksum/secret-sql-tls: {{ include (print $.Template.BasePath "/Secret/sql-tls.yaml") . | sha256sum }} + checksum/secret-tls: {{ include (print $.Template.BasePath "/Secret/tls.yaml") . | sha256sum }} + {{- if .Values.podAnnotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + labels: {{- include "st-common.labels.standard" . | nindent 8 }} + app.kubernetes.io/component: freeradius + {{- if .Values.podLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.podLabels "context" $) | nindent 8 }} + {{- end }} + spec: + {{- if .Values.affinity }} + affinity: {{- include "st-common.tplvalues.render" (dict "value" .Values.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "st-common.affinities.pods" (dict "type" .Values.podAffinityPreset "context" $) | nindent 10 }} + podAntiAffinity: {{- include "st-common.affinities.pods" (dict "type" .Values.podAntiAffinityPreset "context" $) | nindent 10 }} + nodeAffinity: {{- include "st-common.affinities.nodes" (dict "type" .Values.nodeAffinityPreset.type "key" .Values.nodeAffinityPreset.key "values" .Values.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- include "freeradius.imagePullSecrets" . | nindent 6 }} + {{- if .Values.hostAliases }} + hostAliases: {{- include "st-common.tplvalues.render" (dict "value" .Values.hostAliases "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{- include "st-common.tplvalues.render" (dict "value" .Values.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName | quote }} + {{- end }} + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + {{- if .Values.podSecurityContext.enabled }} + securityContext: {{- omit .Values.podSecurityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "freeradius.serviceAccountName" . }} + {{- if .Values.tolerations }} + tolerations: {{- include "st-common.tplvalues.render" (dict "value" .Values.tolerations "context" .) | nindent 8 }} + {{- end }} + {{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "st-common.tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" .) | nindent 8 }} + {{- end }} + {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) .Values.initContainers }} + initContainers: + {{- if .Values.initContainers }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.initContainers "context" $) | nindent 8 }} + {{- end }} + {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }} + - name: volume-permissions + image: {{ include "freeradius.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + command: + - /bin/bash + args: + - -ec + - | + printf '%s\n' "[system] Change permission" >&2 + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} {{ .Values.persistence.mountPath }} + chmod 0711 {{ .Values.persistence.mountPath }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.volumePermissions.resources }} + resources: {{- toYaml .Values.volumePermissions.resources | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ .Values.persistence.mountPath }} + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- end }} + {{- end }} + containers: + - name: freeradius + image: {{ include "freeradius.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.diagnosticMode.enabled }} + command: {{- include "st-common.tplvalues.render" (dict "value" .Values.diagnosticMode.command "context" $) | nindent 12 }} + {{- else if .Values.command }} + command: {{- include "st-common.tplvalues.render" (dict "value" .Values.command "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.diagnosticMode.enabled }} + args: {{- include "st-common.tplvalues.render" (dict "value" .Values.diagnosticMode.args "context" $) | nindent 12 }} + {{- else if .Values.args }} + args: {{- include "st-common.tplvalues.render" (dict "value" .Values.args "context" $) | nindent 12 }} + {{- else }} + args: + - -fxx + - -l + - stdout + {{- end }} + env: + {{- if .Values.modsEnabled.sql.enabled }} + - name: FREERADIUS_MODS_SQL_PASSWORD + valueFrom: + secretKeyRef: + {{- if .Values.auth.existingSecretPerPassword }} + name: {{ tpl (include "st-common.secrets.name" (dict "existingSecret" .Values.auth.existingSecretPerPassword.databasePassword "context" $)) $ }} + key: {{ include "st-common.secrets.key" (dict "existingSecret" .Values.auth.existingSecretPerPassword "key" "databasePassword") }} + {{- else }} + name: {{ include "freeradius.database.secretName" . }} + key: {{ include "freeradius.database.secretKey" . }} + {{- end }} + {{- end }} + {{- if .Values.sitesEnabled.status.enabled }} + - name: FREERADIUS_SITES_STATUS_SECRET + valueFrom: + secretKeyRef: + {{- if .Values.auth.existingSecretPerPassword }} + name: {{ tpl (include "st-common.secrets.name" (dict "existingSecret" .Values.auth.existingSecretPerPassword.sitesStatusSecret "context" $)) $ }} + key: {{ include "st-common.secrets.key" (dict "existingSecret" .Values.auth.existingSecretPerPassword "key" "sitesStatusSecret") }} + {{- else }} + name: {{ $globalSecretName }} + key: {{ include "st-common.secrets.key" (dict "existingSecret" .Values.auth.existingSecret "key" "sites-status-secret") }} + {{- end }} + {{- end }} + {{- if .Values.sitesEnabled.tls.enabled }} + - name: FREERADIUS_SITES_TLS_PRIVKEY_PASSWORD + valueFrom: + secretKeyRef: + {{- if .Values.auth.existingSecretPerPassword }} + name: {{ tpl (include "st-common.secrets.name" (dict "existingSecret" .Values.auth.existingSecretPerPassword.sitesTlsPrivKeyPassword "context" $)) $ }} + key: {{ include "st-common.secrets.key" (dict "existingSecret" .Values.auth.existingSecretPerPassword "key" "sitesTlsPrivKeyPassword") }} + {{- else }} + name: {{ $globalSecretName }} + key: {{ include "st-common.secrets.key" (dict "existingSecret" .Values.auth.existingSecret "key" "sites-tls-privkey-password") }} + {{- end }} + {{- end }} + {{- if .Values.extraEnvVars }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + envFrom: + - configMapRef: + name: {{ include "freeradius.names.envvars" . }} + {{- if .Values.extraEnvVarsCM }} + - configMapRef: + name: {{ .Values.extraEnvVarsCM }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + - secretRef: + name: {{ .Values.extraEnvVarsSecret }} + {{- end }} + {{- if .Values.lifecycleHooks }} + lifecycle: {{- include "st-common.tplvalues.render" (dict "value" .Values.lifecycleHooks "context" $) | nindent 12 }} + {{- end }} + ports: + - name: auth + containerPort: {{ .Values.containerPorts.auth }} + protocol: UDP + - name: acct + containerPort: {{ .Values.containerPorts.acct }} + protocol: UDP + {{- if .Values.sitesEnabled.coa.enabled }} + - name: coa + containerPort: {{ .Values.containerPorts.coa }} + protocol: UDP + {{- end }} + {{- if .Values.tls.enabled }} + - name: radsec + containerPort: {{ .Values.containerPorts.radsec }} + protocol: TCP + {{- end }} + {{- if .Values.sitesEnabled.status.enabled }} + - name: status + containerPort: {{ .Values.containerPorts.status }} + protocol: UDP + {{- end }} + {{- if not .Values.diagnosticMode.enabled }} + {{- if .Values.customStartupProbe }} + startupProbe: {{- include "st-common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.startupProbe.enabled }} + startupProbe: {{- include "st-common.tplvalues.render" (dict "value" (omit .Values.startupProbe "enabled") "context" $) | nindent 12 }} + exec: + command: + - sh + - -c + - | + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + if [[ ! -f "{{ .Values.persistence.mountPath }}/.user_scripts_initialized" ]]; then + echo "Init scripts still not executed. Skipping check" + exit 1 + fi + {{- end }} + /bin/echo "Message-Authenticator = 0x00" | /usr/bin/radclient 127.0.0.1:${FREERADIUS_SITES_STATUS_PORT} status ${FREERADIUS_SITES_STATUS_SECRET} + {{- end }} + {{- if .Values.customLivenessProbe }} + livenessProbe: {{- include "st-common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.livenessProbe.enabled }} + livenessProbe: {{- omit .Values.livenessProbe "enabled" | toYaml | nindent 12 }} + exec: + command: + - sh + - -c + - >- + /bin/echo "Message-Authenticator = 0x00" | /usr/bin/radclient 127.0.0.1:${FREERADIUS_SITES_STATUS_PORT} status ${FREERADIUS_SITES_STATUS_SECRET} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "st-common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- omit .Values.readinessProbe "enabled" | toYaml | nindent 12 }} + exec: + command: + - sh + - -c + - >- + /bin/echo "Message-Authenticator = 0x00" | /usr/bin/radclient 127.0.0.1:${FREERADIUS_SITES_STATUS_PORT} status ${FREERADIUS_SITES_STATUS_SECRET} + {{- end }} + {{- end }} + {{- if .resources }} + resources: {{- include "st-common.tplvalues.render" (dict "value" .resources "context" $) | nindent 12 }} + {{- else if and .resourcesPreset (ne .resourcesPreset "none") }} + resources: {{- include "st-common.resources.preset" (dict "type" .resourcesPreset) | nindent 12 }} + {{- end }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: {{ default "/startechnica/freeradius" .Values.persistence.mountPath }} + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if or (.Files.Glob "files/radiusd.conf") .Values.configuration .Values.configurationConfigMap }} + - name: freeradius-config + mountPath: /etc/freeradius/radiusd.conf + subPath: radiusd.conf + {{- end }} + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if .Values.modsEnabled.sql.enabled }} + - name: freeradius-mods + mountPath: /etc/freeradius/mods-enabled/sql + subPath: sql + {{- end }} + - name: freeradius-sites + mountPath: /etc/freeradius/sites-enabled/default + subPath: default + - name: freeradius-sites + mountPath: /etc/freeradius/sites-enabled/status + subPath: status + {{- if .Values.sitesEnabled.coa.enabled }} + - name: freeradius-sites + mountPath: /etc/freeradius/sites-enabled/coa + subPath: coa + {{- end }} + {{- if .Values.tls.enabled }} + - name: freeradius-sites + mountPath: /etc/freeradius/sites-enabled/tls + subPath: tls + - name: freeradius-tls + mountPath: /opt/startechnica/freeradius/certs + readOnly: true + {{- end }} + {{- if and .Values.modsEnabled.sql.enabled (eq .Values.modsEnabled.sql.dialect "sqlite") }} + - name: freeradius-sqlite + mountPath: {{ .Values.modsEnabled.sql.sqlite.filename | quote }} + {{- end }} + {{- if .Values.modsEnabled.sql.tls.enabled }} + - name: freeradius-sql-tls + mountPath: /opt/startechnica/freeradius/certs + {{- end }} + - name: shared-certs + mountPath: /opt/startechnica/freeradius/shared-certs + readOnly: true + - name: temp + mountPath: /startechnica/freeradius/tmp + {{- if .Values.extraVolumeMounts }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.extraVolumeMounts "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.sidecars }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.sidecars "context" $) | nindent 8 }} + {{- end }} + volumes: + - name: freeradius-mods + configMap: + name: {{ printf "%s-mods" (include "st-common.names.fullname" .) }} + - name: freeradius-sites + configMap: + name: {{ printf "%s-sites" (include "st-common.names.fullname" .) }} + - name: temp + emptyDir: {} + - name: shared-certs + emptyDir: {} + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "freeradius.claimName" . }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if and .Values.modsEnabled.sql.enabled (eq .Values.modsEnabled.sql.dialect "sqlite") }} + - name: freeradius-sqlite + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: freeradius-tls + secret: + secretName: {{ include "freeradius.tlsSecretName" . }} + {{- end }} + {{- if .Values.modsEnabled.sql.tls.enabled }} + - name: freeradius-sql-tls + secret: + secretName: {{ include "freeradius.sqlTlsSecretName" . }} + items: + - key: tls.crt + path: sql-tls.crt + - key: tls.key + path: sql-tls.key + - key: ca.crt + path: sql-ca.crt + {{- end }} + {{- if or (.Files.Glob "files/radiusd.conf") .Values.configuration .Values.configurationConfigMap }} + - name: freeradius-config + configMap: + name: {{ include "freeradius.configurationCM" . }} + {{- end }} + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ include "freeradius.initdbScriptsCM" . }} + {{- end }} + {{- if .Values.extraVolumes }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.extraVolumes "context" $) | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/templates/Istio/Gateway.yaml b/templates/Istio/Gateway.yaml new file mode 100644 index 0000000..c1232f8 --- /dev/null +++ b/templates/Istio/Gateway.yaml @@ -0,0 +1,69 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.gateway.enabled (not .Values.gateway.existingGateway) }} +{{- if not (eq (include "st-common.capabilities.istioGateway.apiVersion" .) "false") }} +apiVersion: {{ include "st-common.capabilities.istioGateway.apiVersion" . }} +kind: Gateway +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +spec: + selector: + istio.io/gateway-name: {{ default "ingressgateway" .Values.gateway.name }} + servers: + - port: + name: auth + number: {{ .Values.service.ports.auth }} + protocol: UDP + hosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host.name | quote }} + {{- end }} + - port: + name: acct + number: {{ .Values.service.ports.acct }} + protocol: UDP + hosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host.name | quote }} + {{- end }} + - port: + name: coa + number: {{ .Values.service.ports.coa }} + protocol: UDP + hosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host.name | quote }} + {{- end }} + - port: + name: radsec + number: {{ .Values.service.ports.radsec }} + protocol: TLS + hosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host.name | quote }} + {{- end }} + tls: + mode: PASSTHROUGH + {{- if .Values.sitesEnabled.tls.enabled }} + credentialName: {{ include "freeradius.tlsSecretName" . }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/Istio/VirtualService.yaml b/templates/Istio/VirtualService.yaml new file mode 100644 index 0000000..bbbf70b --- /dev/null +++ b/templates/Istio/VirtualService.yaml @@ -0,0 +1,47 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.gateway.enabled (not .Values.gateway.existingVirtualService) }} +{{- if not (eq (include "st-common.capabilities.istioVirtualService.apiVersion" .) "false") }} +apiVersion: {{ include "st-common.capabilities.istioVirtualService.apiVersion" . }} +kind: VirtualService +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +spec: + gateways: + - {{ printf "%s/%s" (include "st-common.names.namespace" .) (include "st-common.names.fullname" .) }} + hosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host | quote }} + {{- end }} + tls: + - match: + - port: {{ .Values.service.ports.radsec }} + sniHosts: + - {{ .Values.ingress.hostname }} + {{- range $host := .Values.ingress.extraHosts }} + - {{ $host | quote }} + {{- end }} + route: + - destination: + # host: {{ printf "%s.%s.svc.%s" (include "st-common.names.fullname" .) (include "st-common.names.namespace" .) .Values.clusterDomain }} + host: {{ printf "%s.%s.svc.cluster.local" (include "st-common.names.fullname" .) (include "st-common.names.namespace" .) }} + port: + number: {{ .Values.service.ports.radsec }} +{{- end }} +{{- end }} diff --git a/templates/NetworkPolicy.yaml b/templates/NetworkPolicy.yaml new file mode 100644 index 0000000..35e544a --- /dev/null +++ b/templates/NetworkPolicy.yaml @@ -0,0 +1,57 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.networkPolicy.enabled }} +apiVersion: {{ include "st-common.capabilities.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: {{- include "st-common.labels.matchLabels" . | nindent 6 }} + ingress: + - ports: + - port: {{ .Values.containerPorts.auth }} + protocol: UDP + - port: {{ .Values.containerPorts.acct }} + protocol: UDP + {{- if .Values.tls.enabled }} + - port: {{ .Values.containerPorts.radsec }} + protocol: TCP + {{- end }} + {{- if .Values.metrics.enabled }} + - port: {{ .Values.containerPorts.metrics }} + protocol: TCP + {{- end }} + {{- if .Values.sitesEnabled.coa.enabled }} + - port: {{ .Values.containerPorts.coa }} + protocol: UDP + {{- end }} + {{- if .Values.sitesEnabled.status.enabled }} + - port: {{ .Values.containerPorts.status }} + protocol: UDP + {{- end }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ include "st-common.names.fullname" . }}-client: "true" + - podSelector: + matchLabels: {{- include "st-common.labels.matchLabels" . | nindent 14 }} + app.kubernetes.io/component: freeradius + {{- if .Values.networkPolicy.additionalRules }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.networkPolicy.additionalRules "context" $) | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/templates/PersistentVolumeClaim.yaml b/templates/PersistentVolumeClaim.yaml new file mode 100644 index 0000000..0cd0acc --- /dev/null +++ b/templates/PersistentVolumeClaim.yaml @@ -0,0 +1,38 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if or .Values.persistence.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.persistence.annotations }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.persistence.annotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + accessModes: + {{- if not (empty .Values.persistence.accessModes) }} + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + {{- else }} + - {{ .Values.persistence.accessMode | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- include "st-common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) | nindent 2 }} +{{- end -}} \ No newline at end of file diff --git a/templates/PodDisruptionBudget.yaml b/templates/PodDisruptionBudget.yaml new file mode 100644 index 0000000..a4b619e --- /dev/null +++ b/templates/PodDisruptionBudget.yaml @@ -0,0 +1,28 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.podDisruptionBudget.create }} +apiVersion: {{ include "st-common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: {{ include "st-common.labels.matchLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/templates/PrometheusRule.yaml b/templates/PrometheusRule.yaml new file mode 100644 index 0000000..fafd180 --- /dev/null +++ b/templates/PrometheusRule.yaml @@ -0,0 +1,25 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{ if and .Values.metrics.enabled .Values.metrics.prometheusRules.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.metrics.prometheusRules.additionalLabels "context" $) | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +spec: + groups: + - name: {{ include "st-common.names.fullname" . }} + rules: + {{- toYaml .Values.metrics.prometheusRules.rules | nindent 6 }} +{{ end }} \ No newline at end of file diff --git a/templates/Role.yaml b/templates/Role.yaml new file mode 100644 index 0000000..89bcc15 --- /dev/null +++ b/templates/Role.yaml @@ -0,0 +1,29 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.rbac.create }} +apiVersion: {{ include "st-common.capabilities.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +rules: + - apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch +{{- end }} \ No newline at end of file diff --git a/templates/RoleBinding.yaml b/templates/RoleBinding.yaml new file mode 100644 index 0000000..1975a59 --- /dev/null +++ b/templates/RoleBinding.yaml @@ -0,0 +1,26 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and .Values.serviceAccount.create .Values.rbac.create }} +apiVersion: {{ include "st-common.capabilities.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +subjects: + - kind: ServiceAccount + name: {{ include "freeradius.serviceAccountName" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "st-common.names.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/templates/Secret/credentials.yaml b/templates/Secret/credentials.yaml new file mode 100644 index 0000000..6618ad5 --- /dev/null +++ b/templates/Secret/credentials.yaml @@ -0,0 +1,38 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (not .Values.auth.existingSecret) (not .Values.auth.existingSecretPerPassword) }} +{{- $secretName := include "st-common.secrets.name" (dict "existingSecret" .Values.auth.existingSecret "context" $) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if and (not .Values.mariadb.enabled) (not .Values.externalDatabase.existingSecret) }} + database-password: {{ include "st-common.secrets.passwords.manage" (dict "secret" $secretName "key" "database-password" "length" 10 "providedValues" (list "externalDatabase.password") "context" $) }} + {{- end }} + {{- if and (.Values.mariadb.enabled) (not (empty .Values.mariadb.auth.username)) }} + mariadb-password: {{ include "st-common.secrets.passwords.manage" (dict "secret" $secretName "key" "mariadb-password" "providedValues" (list "mariadb.auth.password") "context" $) }} + {{- end }} + {{- if (.Values.sitesEnabled.status.enabled) }} + sites-status-secret: {{ include "st-common.secrets.passwords.manage" (dict "secret" $secretName "key" "sites-status-secret" "length" 10 "providedValues" (list "sitesEnabled.status.secret") "context" $) }} + {{- end }} + {{- if (.Values.sitesEnabled.tls.enabled) }} + sites-tls-privkey-password: {{ include "st-common.secrets.passwords.manage" (dict "secret" $secretName "key" "sites-tls-privkey-password" "length" 10 "providedValues" (list "sitesEnabled.tls.privateKeyPassword") "context" $) }} + {{- end }} + {{- if (.Values.modsEnabled.sql.tls.enabled) }} + mods-sql-tls-privkey-password: {{ include "st-common.secrets.passwords.manage" (dict "secret" $secretName "key" "mods-sql-tls-privkey-password" "length" 10 "providedValues" (list "modsEnabled.sql.tls.privateKeyPassword") "context" $) }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/templates/Secret/sql-tls.yaml b/templates/Secret/sql-tls.yaml new file mode 100644 index 0000000..e49a5e2 --- /dev/null +++ b/templates/Secret/sql-tls.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "freeradius.createSqlTlsSecret" .) (not .Values.tls.autoGenerator.certmanager.enabled) }} +{{- $ca := genCA "freeradius-ca" 365 }} +{{- $releaseNamespace := include "st-common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "st-common.names.fullname" . }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "%s.%s.svc" $fullname $releaseNamespace) (printf "%s.%s" $fullname $releaseNamespace) $fullname }} +{{- $crt := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "st-common.names.fullname" . }}-sql-tls + namespace: {{ include "st-common.names.namespace" . | quote }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ $ca.Cert | b64enc | quote }} + tls.crt: {{ $crt.Cert | b64enc | quote }} + tls.key: {{ $crt.Key | b64enc | quote }} +{{- end }} \ No newline at end of file diff --git a/templates/Secret/tls.yaml b/templates/Secret/tls.yaml new file mode 100644 index 0000000..3b182d5 --- /dev/null +++ b/templates/Secret/tls.yaml @@ -0,0 +1,30 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if and (include "freeradius.createTlsSecret" .) (not .Values.tls.autoGenerator.certmanager.enabled) }} +{{- $ca := genCA "freeradius-ca" 365 }} +{{- $releaseNamespace := include "st-common.names.namespace" . }} +{{- $clusterDomain := .Values.clusterDomain }} +{{- $fullname := include "st-common.names.fullname" . }} +{{- $altNames := list (printf "*.%s.%s.svc.%s" $fullname $releaseNamespace $clusterDomain) (printf "%s.%s.svc" $fullname $releaseNamespace) (printf "%s.%s" $fullname $releaseNamespace) $fullname }} +{{- $crt := genSignedCert $fullname nil $altNames 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "st-common.names.fullname" . }}-tls + namespace: {{ include "st-common.names.namespace" . | quote }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + ca.crt: {{ $ca.Cert | b64enc | quote }} + tls.crt: {{ $crt.Cert | b64enc | quote }} + tls.key: {{ $crt.Key | b64enc | quote }} +{{- end }} \ No newline at end of file diff --git a/templates/Service.yaml b/templates/Service.yaml new file mode 100644 index 0000000..7571125 --- /dev/null +++ b/templates/Service.yaml @@ -0,0 +1,98 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "st-common.names.fullname" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if or .Values.service.annotations .Values.commonAnnotations .Values.metrics.annotations }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.service.annotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.service.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.annotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.metrics.annotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ default "ClusterIP" .Values.service.type }} + {{- if eq .Values.service.type "LoadBalancer" }} + allocateLoadBalancerNodePorts: {{ eq .Values.service.allocateLoadBalancerNodePorts "true" }} + {{- end }} + {{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and .Values.service.externalTrafficPolicy (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerClass)) }} + loadBalancerClass: {{ .Values.service.loadBalancerClass }} + {{- end }} + {{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }} + loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }} + {{- end }} + {{- if .Values.service.sessionAffinity }} + sessionAffinity: {{ .Values.service.sessionAffinity }} + {{- end }} + {{- if .Values.service.sessionAffinityConfig }} + sessionAffinityConfig: {{- include "st-common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }} + {{- end }} + ports: + - name: udp-auth + port: {{ .Values.service.ports.auth }} + protocol: UDP + targetPort: {{ .Values.containerPorts.auth }} + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.nodePorts.auth) }} + nodePort: {{ coalesce .Values.service.nodePorts.auth .Values.service.nodePort }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + - name: udp-acct + port: {{ .Values.service.ports.acct }} + protocol: UDP + targetPort: {{ .Values.containerPorts.acct }} + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.nodePorts.acct) }} + nodePort: {{ .Values.service.nodePorts.acct }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- if .Values.sitesEnabled.coa.enabled }} + - name: udp-coa + port: {{ .Values.service.ports.coa }} + protocol: UDP + targetPort: {{ .Values.containerPorts.coa }} + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.nodePorts.coa) }} + nodePort: {{ .Values.service.nodePorts.coa }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: tcp-radsec + port: {{ .Values.service.ports.radsec }} + protocol: TCP + targetPort: {{ .Values.containerPorts.radsec }} + {{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) .Values.service.nodePorts.radsec) }} + nodePort: {{ .Values.service.nodePorts.radsec }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + {{- end }} + selector: {{ include "st-common.labels.matchLabels" . | nindent 4 }} + app.kubernetes.io/component: freeradius +--- \ No newline at end of file diff --git a/templates/ServiceAccount.yaml b/templates/ServiceAccount.yaml new file mode 100644 index 0000000..9e621e5 --- /dev/null +++ b/templates/ServiceAccount.yaml @@ -0,0 +1,27 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "freeradius.serviceAccountName" . }} + namespace: {{ include "st-common.names.namespace" . | quote }} + labels: {{- include "st-common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: freeradius + {{- if .Values.commonLabels }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonLabels "context" $) | nindent 4 }} + {{- end }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.commonAnnotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.serviceAccount.annotations }} + {{- include "st-common.tplvalues.render" (dict "value" .Values.serviceAccount.annotations "context" $) | nindent 4 }} + {{- end }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} diff --git a/templates/_helpers/_databases.tpl b/templates/_helpers/_databases.tpl new file mode 100644 index 0000000..1bb165c --- /dev/null +++ b/templates/_helpers/_databases.tpl @@ -0,0 +1,95 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). */}} +{{- define "freeradius.mariadb.fullname" -}} + {{- include "st-common.names.dependency.fullname" (dict "chartName" "mariadb" "chartValues" .Values.mariadb "context" $) -}} +{{- end -}} + +{{/* Return the Database hostname */}} +{{- define "freeradius.database.host" -}} +{{- if eq .Values.mariadb.architecture "replication" }} + {{- ternary (include "freeradius.mariadb.fullname" .) .Values.externalDatabase.host .Values.mariadb.enabled -}}-primary +{{- else -}} + {{- ternary (include "freeradius.mariadb.fullname" .) .Values.externalDatabase.host .Values.mariadb.enabled -}} +{{- end -}} +{{- end -}} + +{{/* Return the Database port */}} +{{- define "freeradius.database.port" -}} + {{- ternary "3306" .Values.externalDatabase.port .Values.mariadb.enabled | quote -}} +{{- end -}} + +{{/* Return the Database database name */}} +{{- define "freeradius.database.name" -}} +{{- if .Values.mariadb.enabled }} + {{- if .Values.global.mariadb }} + {{- if .Values.global.mariadb.auth }} + {{- coalesce .Values.global.mariadb.auth.database .Values.mariadb.auth.database -}} + {{- else -}} + {{- .Values.mariadb.auth.database -}} + {{- end -}} + {{- else -}} + {{- .Values.mariadb.auth.database -}} + {{- end -}} +{{- else -}} + {{- .Values.externalDatabase.database -}} +{{- end -}} +{{- end -}} + +{{/* Return the Database user */}} +{{- define "freeradius.database.user" -}} +{{- if .Values.mariadb.enabled }} + {{- if .Values.global.mariadb }} + {{- if .Values.global.mariadb.auth }} + {{- coalesce .Values.global.mariadb.auth.username .Values.mariadb.auth.username -}} + {{- else -}} + {{- .Values.mariadb.auth.username -}} + {{- end -}} + {{- else -}} + {{- .Values.mariadb.auth.username -}} + {{- end -}} +{{- else -}} + {{- .Values.externalDatabase.user -}} +{{- end -}} +{{- end -}} + +{{/* Return the Database encrypted password */}} +{{- define "freeradius.database.secretName" -}} +{{- if .Values.mariadb.enabled }} + {{- if .Values.global.mariadb }} + {{- if .Values.global.mariadb.auth }} + {{- if .Values.global.mariadb.auth.existingSecret }} + {{- tpl .Values.global.mariadb.auth.existingSecret $ -}} + {{- else -}} + {{- default (include "freeradius.mariadb.fullname" .) (tpl .Values.mariadb.auth.existingSecret $) -}} + {{- end -}} + {{- else -}} + {{- default (include "freeradius.mariadb.fullname" .) (tpl .Values.mariadb.auth.existingSecret $) -}} + {{- end -}} + {{- else -}} + {{- default (include "freeradius.mariadb.fullname" .) (tpl .Values.mariadb.auth.existingSecret $) -}} + {{- end -}} +{{- else -}} + {{- default (include "st-common.secrets.name" (dict "existingSecret" .Values.mariadb.auth.existingSecret "context" $)) (tpl .Values.externalDatabase.existingSecret $) -}} +{{- end -}} +{{- end -}} + +{{/* Add environment variables to configure database values */}} +{{- define "freeradius.database.secretKey" -}} +{{- if .Values.mariadb.enabled -}} + {{- print "mariadb-password" -}} +{{- else -}} + {{- if .Values.externalDatabase.existingSecret -}} + {{- if .Values.externalDatabase.existingSecretPasswordKey -}} + {{- printf "%s" .Values.externalDatabase.existingSecretPasswordKey -}} + {{- else -}} + {{- print "database-password" -}} + {{- end -}} + {{- else -}} + {{- print "database-password" -}} + {{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/templates/_helpers/_helpers.tpl b/templates/_helpers/_helpers.tpl new file mode 100644 index 0000000..35ff55e --- /dev/null +++ b/templates/_helpers/_helpers.tpl @@ -0,0 +1,140 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* Create the name of the service account to use */}} +{{- define "freeradius.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} + {{- default (include "st-common.names.fullname" .) .Values.serviceAccount.name }} +{{- else }} + {{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* Return the path to the cert file. */}} +{{- define "freeradius.tlsCert" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/tls.crt" -}} +{{- else -}} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.tls.certFilename -}} +{{- end -}} +{{- end -}} + +{{/* Return the path to the cert key file. */}} +{{- define "freeradius.tlsCertKey" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/tls.key" -}} +{{- else -}} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.tls.certKeyFilename -}} +{{- end -}} +{{- end -}} + +{{/* Return the path to the CA cert file. */}} +{{- define "freeradius.tlsCACert" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/ca.crt" -}} +{{- else -}} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.tls.certCAFilename -}} +{{- end -}} +{{- end -}} + +{{/* Create the name of the SSL certificate to use */}} +{{- define "freeradius.tlsSecretName" -}} +{{- if .Values.tls.certificatesSecret }} + {{ .Values.tls.certificatesSecret }} +{{- else }} + {{- default (printf "%s-tls" (include "st-common.names.fullname" .)) }} +{{- end }} +{{- end -}} + +{{/* Return true if a TLS secret object should be created */}} +{{- define "freeradius.createTlsSecret" -}} +{{- if and .Values.tls.enabled .Values.tls.autoGenerated (not .Values.tls.certificatesSecret) }} + {{- true }} +{{- end }} +{{- end -}} + +{{/* Validate values of FreeRADIUS - Auth TLS enabled */}} +{{- define "freeradius.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.tls.autoGenerated) (not .Values.tls.certificatesSecret) }} +freeradius: tls.enabled + In order to enable TLS, you also need to provide + an existing secret containing the Keystore and Truststore or + enable auto-generated certificates. +{{- end }} +{{- end -}} + +{{/* Return the path to the SQL cert file. */}} +{{- define "freeradius.sqlTlsCert" -}} +{{- if and .Values.modsEnabled.sql.tls.enabled }} + {{- if .Values.modsEnabled.sql.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/sql-tls.crt" -}} + {{- else if not (empty .Values.modsEnabled.sql.tls.certFilename) }} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.modsEnabled.sql.tls.certFilename -}} + {{- end }} +{{- else }} + {{- printf "" -}} +{{- end }} +{{- end -}} + +{{/* Return the path to the SQL cert key file. */}} +{{- define "freeradius.sqlTlsCertKey" -}} +{{- if and .Values.modsEnabled.sql.tls.enabled }} + {{- if .Values.modsEnabled.sql.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/sql-tls.key" -}} + {{- else if not (empty .Values.modsEnabled.sql.tls.certKeyFilename) }} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.modsEnabled.sql.tls.certKeyFilename -}} + {{- end }} +{{- else }} + {{- printf "" -}} +{{- end }} +{{- end -}} + +{{/* Return the path to the SQL CA cert file. */}} +{{- define "freeradius.sqlTlsCACert" -}} +{{- if and .Values.modsEnabled.sql.tls.enabled }} + {{- if .Values.modsEnabled.sql.tls.autoGenerated }} + {{- printf "/opt/startechnica/freeradius/certs/sql-ca.crt" -}} + {{- else if not (empty .Values.modsEnabled.sql.tls.certCAFilename)}} + {{- printf "/opt/startechnica/freeradius/certs/%s" .Values.modsEnabled.sql.tls.certCAFilename -}} + {{- end }} +{{- else }} + {{- printf "" -}} +{{- end }} +{{- end -}} + +{{/* Create the name of the secret for SQL SSL certificate to use */}} +{{- define "freeradius.sqlTlsSecretName" -}} +{{- if .Values.modsEnabled.sql.tls.certificatesSecret }} + {{ .Values.modsEnabled.sql.tls.certificatesSecret }} +{{- else }} + {{- default (printf "%s-sql-tls" (include "st-common.names.fullname" .)) }} +{{- end }} +{{- end -}} + +{{/* Return true if a TLS secret object should be created */}} +{{- define "freeradius.createSqlTlsSecret" -}} +{{- if and .Values.modsEnabled.sql.tls.enabled .Values.modsEnabled.sql.tls.autoGenerated (not .Values.modsEnabled.sql.tls.certificatesSecret) }} + {{- true }} +{{- end }} +{{- end -}} + +{{/* Get the configuration ConfigMap name. */}} +{{- define "freeradius.configurationCM" -}} +{{- if .Values.configurationConfigMap -}} + {{- printf "%s" (tpl .Values.configurationConfigMap $) -}} +{{- else -}} + {{- printf "%s-configuration" (include "st-common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* Get the initialization scripts ConfigMap name. */}} +{{- define "freeradius.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} + {{- printf "%s" .Values.initdbScriptsConfigMap -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "st-common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + diff --git a/templates/_helpers/_images.tpl b/templates/_helpers/_images.tpl new file mode 100644 index 0000000..4d9840b --- /dev/null +++ b/templates/_helpers/_images.tpl @@ -0,0 +1,14 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* Return the proper FreeRADIUS image name */}} +{{- define "freeradius.image" -}} + {{ include "st-common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* Return the proper Docker Image Registry Secret Names */}} +{{- define "freeradius.imagePullSecrets" -}} + {{- include "st-common.images.pullSecrets" (dict "images" (list .Values.image .Values.volumePermissions.image .Values.metrics.image) "global" .Values.global) -}} +{{- end -}} \ No newline at end of file diff --git a/templates/_helpers/_names.tpl b/templates/_helpers/_names.tpl new file mode 100644 index 0000000..e4c9bec --- /dev/null +++ b/templates/_helpers/_names.tpl @@ -0,0 +1,10 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* vim: set filetype=mustache: */}} + +{{- define "freeradius.names.envvars" -}} +{{- printf "%s-envvars" (include "st-common.names.fullname" .) -}} +{{- end -}} \ No newline at end of file diff --git a/templates/_helpers/_volumes.tpl b/templates/_helpers/_volumes.tpl new file mode 100644 index 0000000..d636769 --- /dev/null +++ b/templates/_helpers/_volumes.tpl @@ -0,0 +1,18 @@ +{{- /* +Copyright (c) 2025 Firmansyah Nainggolan. All Rights Reserved. +SPDX-License-Identifier: APACHE-2.0 +*/}} + +{{/* Return the FreeRADIUS PVC name. */}} +{{- define "freeradius.claimName" -}} +{{- if .Values.persistence.existingClaim }} + {{- printf "%s" (tpl .Values.persistence.existingClaim $) -}} +{{- else }} + {{- printf "%s" (include "st-common.names.fullname" .) -}} +{{- end }} +{{- end -}} + +{{/* Return the proper image name (for the init container volume-permissions image) */}} +{{- define "freeradius.volumePermissions.image" -}} + {{ include "st-common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} \ No newline at end of file diff --git a/values-test.yaml b/values-test.yaml new file mode 100644 index 0000000..059a3c5 --- /dev/null +++ b/values-test.yaml @@ -0,0 +1,44 @@ +persistence: + enabled: true +# storageClass: + +service: + type: LoadBalancer + externalTrafficPolicy: Local + ipFamilyPolicy: PreferDualStack + +modsEnabled: + sql: + enabled: true + dialect: mysql + +externalDatabase: + # host: mariadb-infra-mariadb-galera.mariadb-infra.svc + host: mariadb-primary.mariadb.svc + port: 3306 + user: radius_user + database: radiusdb + password: "aserfdertg" + +sitesEnabled: + coa: + enabled: true + tls: + enabled: true + +tls: + enabled: true + autoGenerated: true + +# updateStrategy: +# type: Recreate + +volumePermissions: + enabled: true + +gateway: + enabled: true + dedicated: false + gatewayApi: false + name: "freeradius" + namespace: "istio-ingress" \ No newline at end of file diff --git a/values.yaml b/values.yaml new file mode 100644 index 0000000..62c1dc7 --- /dev/null +++ b/values.yaml @@ -0,0 +1,985 @@ +## @section Global parameters + +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters + +## @param kubeVersion Force target Kubernetes version (using Helm capabilities if not set) +## +kubeVersion: "" +## @param nameOverride String to partially override freeradius.fullname +## +nameOverride: "" +## @param namespaceOverride String to partially override freeradius.namespace +## +namespaceOverride: "" +## @param fullnameOverride String to fully override adminer.fullname +## +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Default Kubernetes cluster domain +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @section FreeRADIUS Image parameters + +## FreeRADIUS image +## ref: https://hub.docker.com/r/freeradius/freeradius-server/tags +## @param image.registry FreeRADIUS image registry +## @param image.repository FreeRADIUS image repository +## @param image.tag FreeRADIUS image tag (immutable tags are recommended) +## @param image.pullPolicy FreeRADIUS image pull policy +## @param image.pullSecrets Specify docker-registry secret names as an array +## @param image.debug Specify if debug logs should be enabled +## +image: + registry: docker.io + repository: freeradius/freeradius-server + tag: "3.2.7" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Set to true if you would like to see extra information on logs + ## It turns BASH and/or NAMI debugging in the image + ## + debug: false + +## @param architecture FreeRADIUS architecture (`standalone` or `replication`) +## +architecture: standalone + +auth: + ## @param auth.createClientUser Create client user on boot + ## + createClientUser: true + ## @param auth.clientUser FreeRADIUS administrator user + ## + clientUser: user + ## @param auth.clientPassword FreeRADIUS administrator password for the new user + ## + clientUserPassword: "" + ## @param auth.existingSecret An already existing secret containing auth info + ## e.g: + ## existingSecret: + ## name: mySecret + ## keyMapping: + ## client-user-password: myPasswordKey + ## + existingSecret: "" + ## @param auth.existingSecretPerPassword Override `existingSecret` and other secret values + ## e.g: + ## existingSecretPerPassword: + ## keyMapping: + ## clientUserPassword: FREERADIUS_ADMIN_PASSWORD + ## databasePassword: password + ## databasePassword: + ## name: freeradius.pocwatt-freeradius-cluster.credentials + ## + existingSecretPerPassword: {} + +## @param configuration FreeRADIUS Configuration. Auto-generated based on other parameters when not specified +## Specify content for keycloak.conf +## NOTE: This will override configuring FreeRADIUS based on environment variables (including those set by the chart) +## The radiusd.conf is auto-generated based on other parameters when this parameter is not specified +## +## Example: +## configuration: |- +## foo: bar +## baz: +## +configuration: "" +## @param configurationConfigMap ConfigMap with the FreeRADIUS configuration files (Note: Overrides `radiusdConfiguration`). The value is evaluated as a template. +## +configurationConfigMap: "" +## @param existingConfigmap Name of existing ConfigMap with FreeRADIUS configuration +## NOTE: When it's set the configuration parameter is ignored +## +existingConfigmap: "" +## @param extraStartupArgs Extra default startup args +## +extraStartupArgs: "" +## initdb scripts +## @param initdbScripts Specify dictionary of scripts to be run at first boot +## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory +## e.g: +## initdbScripts: +## my_init_script.sh: | +## #!/bin/sh +## echo "Do something." +## +initdbScripts: {} +## @param initdbScriptsConfigMap ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`) +## +initdbScriptsConfigMap: "" +## @param primary.command Override default container command on FreeRADIUS container(s) (useful when using custom images) +## +command: [] +## @param primary.args Override default container args on FreeRADIUS container(s) (useful when using custom images) +## +args: [] +## @param primary.lifecycleHooks for the FreeRADIUS container(s) to automate configuration before or after startup +## +lifecycleHooks: {} +## @param primary.hostAliases Add deployment host aliases +## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ +## +hostAliases: [] +## @param primary.configuration [string] FreeRADIUS configuration to be injected as ConfigMap +## ref: https://mysql.com/kb/en/mysql/configuring-mysql-with-mycnf/#example-of-configuration-file +## + +## @section FreeRADIUS Deployment parameters + +## @param replicaCount Desired number of cluster nodes +## +replicaCount: 1 +## @param updateStrategy.type updateStrategy for FreeRADIUS Master StatefulSet +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## +updateStrategy: + type: RollingUpdate +## @param podLabels Extra labels for FreeRADIUS pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} +## @param podAnnotations Annotations for FreeRADIUS pods +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAffinityPreset: "" +## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard` +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity +## +podAntiAffinityPreset: soft +## Node affinity preset +## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity +## +nodeAffinityPreset: + ## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard` + ## + type: "" + ## @param nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set. + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set. + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + +## @param affinity Affinity for FreeRADIUS pods assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## Note: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set +## +affinity: {} +## @param nodeSelector Node labels for FreeRADIUS pods assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +## +nodeSelector: {} +## @param tolerations Tolerations for FreeRADIUS pods assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] +## @param topologySpreadConstraints Topology Spread Constraints for FreeRADIUS pods assignment +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## E.g. +## topologySpreadConstraints: +## - maxSkew: 1 +## topologyKey: topology.kubernetes.io/zone +## whenUnsatisfiable: DoNotSchedule +## +topologySpreadConstraints: {} + +## @param priorityClassName Priority class for FreeRADIUS pods assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ +## +priorityClassName: "" +## @param schedulerName Name of the k8s scheduler (other than default) +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param podManagementPolicy podManagementPolicy to manage scaling operation of FreeRADIUS pods +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies +## +podManagementPolicy: "" + +## @param containerPorts.auth FreeRADIUS Auth container port +## @param containerPorts.acct FreeRADIUS Accounting container port +## @param containerPorts.status FreeRADIUS Status HTTP container port +## +containerPorts: + auth: 1812 + acct: 1813 + coa: 3799 + radsec: 2083 + status: 18121 +## FreeRADIUS Pod security context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod +## @param podSecurityContext.enabled Enable security context for FreeRADIUS pods +## @param podSecurityContext.fsGroup Group ID for the mounted volumes' filesystem +## +podSecurityContext: + enabled: false + fsGroup: 101 + runAsUser: 101 +## FreeRADIUS container security context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## @param containerSecurityContext.enabled FreeRADIUS container securityContext +## @param containerSecurityContext.runAsUser User ID for the FreeRADIUS container +## @param containerSecurityContext.runAsNonRoot Set Controller container's Security Context runAsNonRoot +## +containerSecurityContext: + enabled: true + allowPrivilegeEscalation: false + capabilities: + add: + - SYS_PTRACE + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsUser: 101 + runAsNonRoot: true + +## Resource requests and limits +## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ +## We usually recommend not to specify default resources and to leave this as a conscious +## choice for the user. This also increases chances charts run on environments with little +## resources, such as Minikube. If you do want to specify resources, uncomment the following +## lines, adjust them as necessary, and remove the curly braces after 'resources:'. +## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production). +## More information: https://github.com/startechnica/apps/blob/main/charts/common/templates/_resources.tpl#L15 +## +resourcesPreset: "nano" +## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads) +## Example: +## resources: +## requests: +## cpu: 2 +## memory: 512Mi +## limits: +## cpu: 3 +## memory: 1024Mi +## +resources: {} + +## Configure extra options for FreeRADIUS containers' liveness, readiness and startup probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) +## @param startupProbe.enabled Enable startupProbe +## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe +## @param startupProbe.periodSeconds Period seconds for startupProbe +## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe +## @param startupProbe.failureThreshold Failure threshold for startupProbe +## @param startupProbe.successThreshold Success threshold for startupProbe +## +startupProbe: + enabled: false + initialDelaySeconds: 120 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 10 + successThreshold: 1 +## Configure extra options for liveness probe +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes +## @param livenessProbe.enabled Enable livenessProbe +## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe +## @param livenessProbe.periodSeconds Period seconds for livenessProbe +## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe +## @param livenessProbe.failureThreshold Failure threshold for livenessProbe +## @param livenessProbe.successThreshold Success threshold for livenessProbe +## +livenessProbe: + enabled: true + initialDelaySeconds: 120 + periodSeconds: 60 + timeoutSeconds: 2 + failureThreshold: 3 + successThreshold: 1 +## @param readinessProbe.enabled Enable readinessProbe +## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe +## @param readinessProbe.periodSeconds Period seconds for readinessProbe +## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe +## @param readinessProbe.failureThreshold Failure threshold for readinessProbe +## @param readinessProbe.successThreshold Success threshold for readinessProbe +## +readinessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + successThreshold: 1 +## @param customStartupProbe Override default startup probe for FreeRADIUS containers +## +customStartupProbe: {} +## @param customLivenessProbe Override default liveness probe for FreeRADIUS containers +## +customLivenessProbe: {} +## @param customReadinessProbe Override default readiness probe for FreeRADIUS containers +## +customReadinessProbe: {} +## @param startupWaitOptions Override default builtin startup wait check options for FreeRADIUS containers +## `bitnami/mariadb` Docker image has built-in startup check mechanism, +## which periodically checks if FreeRADIUS service has started up and stops it +## if all checks have failed after X tries. Use these to control these checks. +## ref: https://github.com/bitnami/bitnami-docker-mariadb/pull/240 +## Example (with default options): +## startupWaitOptions: +## retries: 300 +## waitTime: 2 +## +startupWaitOptions: {} +## @param extraFlags FreeRADIUS additional command line flags +## Can be used to specify command line flags, for example: +## E.g. +## extraFlags: "--max-connect-errors=1000 --max_connections=155" +## +extraFlags: "" +## @param extraEnvVars Extra environment variables to be set on FreeRADIUS containers +## E.g. +## extraEnvVars: +## - name: TZ +## value: "Europe/Paris" +## +extraEnvVars: [] +## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars for FreeRADIUS containers +## +extraEnvVarsCM: "" +## @param extraEnvVarsSecret Name of existing Secret containing extra env vars for FreeRADIUS containers +## +extraEnvVarsSecret: "" + +## @section Persistence Parameters + +## Persistence Parameters +## ref: https://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + ## @param persistence.enabled Enable persistence on FreeRADIUS replicas using a `PersistentVolumeClaim` + ## + enabled: false + ## @param persistence.existingClaim Name of an existing `PersistentVolumeClaim` for FreeRADIUS primary replicas + ## NOTE: When it's set the rest of persistence parameters are ignored + ## + existingClaim: "" + ## @param persistence.subPath Subdirectory of the volume to mount at + ## + subPath: "" + ## @param persistence.mountPath Path to mount the volume at + ## + mountPath: /startechnica/freeradius + ## @param persistence.storageClass FreeRADIUS persistent volume storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + storageClass: "" + ## @param persistence.annotations FreeRADIUS persistent volume claim annotations + ## + annotations: {} + ## @param persistence.accessModes FreeRADIUS persistent volume access Modes + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size FreeRADIUS persistent volume size + ## + size: 8Gi + ## @param persistence.selector Selector to match an existing Persistent Volume + ## selector: + ## matchLabels: + ## app: my-app + ## + selector: {} + +## 'volumePermissions' init container parameters +## Changes the owner and group of the persistent volume mount point to runAsUser:fsGroup values +## based on the podSecurityContext/containerSecurityContext parameters +## +volumePermissions: + ## @param volumePermissions.enabled Enable init container that changes the owner/group of the PV mount point to `runAsUser:fsGroup` + ## + enabled: false + ## Bitnami Shell image + ## ref: https://hub.docker.com/r/bitnami/bitnami-shell/tags/ + ## @param volumePermissions.image.registry Bitnami Shell image registry + ## @param volumePermissions.image.repository Bitnami Shell image repository + ## @param volumePermissions.image.tag Bitnami Shell image tag (immutable tags are recommended) + ## @param volumePermissions.image.pullPolicy Bitnami Shell image pull policy + ## @param volumePermissions.image.pullSecrets Bitnami Shell image pull secrets + ## + image: + registry: docker.io + repository: bitnami/os-shell + tag: "11" + digest: "" + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init container's resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## @param volumePermissions.resources.limits The resources limits for the init container + ## @param volumePermissions.resources.requests The requested resources for the init container + ## + resources: + limits: {} + requests: {} + ## Init container Container Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container + ## @param volumePermissions.securityContext.runAsUser Set init container's Security Context runAsUser + ## NOTE: when runAsUser is set to special value "auto", init container will try to chown the + ## data folder to auto-determined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic user ids (and 0 is not allowed) + ## + securityContext: + runAsUser: 0 + +## @param extraVolumes Optionally specify extra list of additional volumes to the FreeRADIUS pod(s) +## +extraVolumes: [] +## @param extraVolumeMounts Optionally specify extra list of additional volumeMounts for the FreeRADIUS container(s) +## +extraVolumeMounts: [] +## @param initContainers Add additional init containers for the FreeRADIUS pod(s) +## +initContainers: [] +## @param sidecars Add additional sidecar containers for the FreeRADIUS pod(s) +## +sidecars: [] + +## @section Traffic Exposure Parameters + +## FreeRADIUS service parameters +## +service: + ## @param service.type FreeRADIUS Kubernetes service type + ## + type: ClusterIP + ## @param service.ports.auth FreeRADIUS Kubernetes service port + ## + ports: + auth: 1812 + acct: 1813 + coa: 3799 + radsec: 2083 + status: 18121 + ## @param service.nodePorts.mysql FreeRADIUS Kubernetes service node port + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + nodePorts: + auth: "" + acct: "" + coa: "" + radsec: "" + status: "" + ## @param service.clusterIP FreeRADIUS Kubernetes service clusterIP IP + ## + clusterIP: "" + ## @param service.loadBalancerIP FreeRADIUS loadBalancerIP if service type is `LoadBalancer` + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + loadBalancerIP: "" + ## @param service.ipFamilyPolicy FreeRADIUS Kubernetes service ipFamilyPolicy policy + ## + ipFamilyPolicy: SingleStack + ## @param service.externalTrafficPolicy Enable client source IP preservation + ## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + ## + externalTrafficPolicy: Cluster + ## @param service.allocateLoadBalancerNodePorts Allow users to disable node ports for Service Type=LoadBalancer. This is useful for + ## bare metal / on-prem environments that rely on VIP based LB implementations. + ## ref https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation + ## + allocateLoadBalancerNodePorts: "false" + ## @param service.loadBalancerClass Enables to use a load balancer implementation other than the cloud provider default. + ## https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + ## + loadBalancerClass: "" + ## @param service.loadBalancerSourceRanges Address that are allowed when FreeRADIUS service is LoadBalancer + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## E.g. + ## loadBalancerSourceRanges: + ## - 10.10.10.0/24 + ## + loadBalancerSourceRanges: [] + ## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value) + ## + extraPorts: [] + ## @param service.annotations Provide any additional annotations which may be required + ## + annotations: {} + ## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP" + ## If "ClientIP", consecutive client requests will be directed to the same Pod + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + ## + sessionAffinity: None + ## @param service.sessionAffinityConfig Additional settings for the sessionAffinity + ## sessionAffinityConfig: + ## clientIP: + ## timeoutSeconds: 300 + sessionAffinityConfig: {} +## Configure the ingress resource that allows you to access the FreeRADIUS installation +## ref: https://kubernetes.io/docs/user-guide/ingress/ +## +ingress: + ## @param ingress.enabled Enable ingress record generation for FreeRADIUS + ## + enabled: false + ## @param ingress.pathType Ingress path type + ## + pathType: ImplementationSpecific + ## @param ingress.apiVersion Force Ingress API version (automatically detected if not set) + ## + apiVersion: "" + ## @param ingress.hostname Default host for the ingress record + ## + hostname: freeradius.local + ## @param ingress.path Default path for the ingress record + ## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers + ## + path: / + ## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations. + ## For a full list of possible ingress annotations, please see + ## ref: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md + ## Use this parameter to set the required annotations for cert-manager, see + ## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations + ## + ## e.g: + ## annotations: + ## kubernetes.io/ingress.class: nginx + ## cert-manager.io/cluster-issuer: cluster-issuer-name + ## + annotations: {} + ## @param ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter + ## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}` + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Rely on cert-manager to create it by setting the corresponding annotations + ## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## DEPRECATED: Use ingress.annotations instead of ingress.certManager + ## certManager: false + ## + + ## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm + ## + selfSigned: false + ## @param ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record + ## e.g: + ## extraHosts: + ## - name: freeradius.local + ## path: / + ## + extraHosts: [] + ## @param ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host + ## e.g: + ## extraPaths: + ## - path: /* + ## backend: + ## serviceName: ssl-redirect + ## servicePort: use-annotation + ## + extraPaths: [] + ## @param ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls + ## e.g: + ## extraTls: + ## - hosts: + ## - freeradius.local + ## secretName: freeradius.local-tls + ## + extraTls: [] + ## @param ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - name: freeradius.local-tls + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+) + ## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster . + ## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/ + ## + ingressClassName: "" + ## @param ingress.extraRules Additional rules to be covered with this ingress record + ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules + ## e.g: + ## extraRules: + ## - host: example.local + ## http: + ## path: / + ## backend: + ## service: + ## name: example-svc + ## port: + ## name: http + ## + extraRules: [] + +## @param revisionHistoryLimit Maximum number of revisions that will be maintained in the Deployment +## +revisionHistoryLimit: 3 + +## @section RBAC parameter +# + +## Specifies whether a ServiceAccount should be created +## +serviceAccount: + ## @param serviceAccount.create Enable the creation of a ServiceAccount for Adminer pods + ## + create: true + ## @param serviceAccount.name Name of the created ServiceAccount + ## If not set and create is true, a name is generated using the fullname template + ## + name: "" + ## @param serviceAccount.automountServiceAccountToken Auto-mount the service account token in the pod + ## + automountServiceAccountToken: false + ## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount + ## + annotations: {} +## Role Based Access +## Ref: https://kubernetes.io/docs/admin/authorization/rbac/ +## +rbac: + ## @param rbac.create Specify whether RBAC resources should be created and used + ## + create: false + ## @param rbac.rules Custom RBAC rules + ## Example: + ## rules: + ## - apiGroups: + ## - "" + ## resources: + ## - pods + ## verbs: + ## - get + ## - list + ## + rules: [] + +## Network Policy configuration +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +## +networkPolicy: + ## @param networkPolicy.enabled Enable the default NetworkPolicy policy + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to the ports Keycloak is listening + ## on. When true, Keycloak will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.additionalRules Additional NetworkPolicy rules + ## Note that all rules are OR-ed. + ## Example: + ## additionalRules: + ## - matchLabels: + ## - role: frontend + ## - matchExpressions: + ## - key: role + ## operator: In + ## values: + ## - frontend + ## + additionalRules: {} + +## Pod disruption budget configuration +## +podDisruptionBudget: + ## @param podDisruptionBudget.create Specifies whether a Pod disruption budget should be created + ## + create: false + ## @param podDisruptionBudget.minAvailable Minimum number / percentage of pods that should remain scheduled + ## + minAvailable: 1 + ## @param podDisruptionBudget.maxUnavailable Maximum number / percentage of pods that may be made unavailable + ## + maxUnavailable: "" + +## MariaDB chart configuration +## ref: https://github.com/bitnami/charts/blob/master/bitnami/mariadb/values.yaml +## @param mariadb.enabled Switch to enable or disable the MariaDB helm chart +## @param mariadb.auth.username Name for a custom user to create +## @param mariadb.auth.password Password for the custom user to create +## @param mariadb.auth.database Name for a custom database to create +## @param mariadb.auth.existingSecret Name of existing secret to use for MariaDB credentials +## @param mariadb.architecture MariaDB architecture (`standalone` or `replication`) +## +mariadb: + enabled: false + auth: + username: freeradius_user + password: "" + database: freeradius_db + existingSecret: "" + architecture: standalone + +## External Database configuration +## All of these values are only used when mariadb.enabled is set to false +## @param externalDatabase.host Database host +## @param externalDatabase.port Database port number +## @param externalDatabase.user Non-root username for FreeRADIUS +## @param externalDatabase.password Password for the non-root username for FreeRADIUS +## @param externalDatabase.database FreeRADIUS database name +## @param externalDatabase.existingSecret Name of an existing secret resource containing the database credentials +## @param externalDatabase.existingSecretPasswordKey Name of an existing secret key containing the database credentials +## +externalDatabase: + host: "" + port: 3306 + user: freeradius_user + database: freeradius_db + password: "" + existingSecret: "" + existingSecretPasswordKey: "" + +modsEnabled: + sql: + enabled: true + dialect: mysql + table: + acct1: radacct + acct2: radacct + authcheck: radcheck + authreply: radreply + client: nas + groupcheck: radgroupcheck + groupreply: radgroupreply + postauth: radpostauth + usergroup: radusergroup + ## @param modsEnabled.sql.groupAttribute The group attribute specific to this instance of rlm_sql + ## + groupAttribute: SQL-Group + ## @param modsEnabled.sql.readClients Set to 'true' to read radius clients from the database ('nas' table) + ## + readClients: true + ## @param modsEnabled.sql.tls.enabled + ## @param modsEnabled.sql.tls.autoGenerated Generate automatically self-signed SQL TLS certificates + ## @param modsEnabled.sql.tls.certificatesSecret + ## @param modsEnabled.sql.tls.certFilename + ## @param modsEnabled.sql.tls.certKeyFilename + ## @param modsEnabled.sql.tls.certCAFilename + ## @param modsEnabled.sql.tls.existingTlsSecret + ## @param modsEnabled.sql.tls.privateKeyPassword + ## + tls: + enabled: false + ciphers: "" + autoGenerated: true + certificatesSecret: "" + certFilename: "" + certKeyFilename: "" + certCAFilename: "" + existingTlsSecret: "" + privateKeyPassword: whatever + + ## @param modsEnabled.sql.sqllite.filename + ## @param modsEnabled.sql.sqllite.busyTimeout + ## + sqlite: + filename: /startechnica/freeradius/freeradius.db + busyTimeout: "200" + +sitesEnabled: + coa: + enabled: false + status: + enabled: true + listen: 127.0.0.1 + secret: adminsecret + tls: + ## @param sitesEnabled.tls.enabled Enable TLS support for radsec traffic + ## + enabled: false + privateKeyPassword: "" + cipher: "DEFAULT" + +clients: + localhost: + ipv4addr: "127.0.0.1" + ipv6addr: "" + proto: udp + secret: password + nasType: other + virtualServer: default + coaServer: coa + limit: + maxConnections: 16 + lifetime: 0 + idleTimeout: 30 + existingConfigMapName: "" + +tls: + ## @param tls.enabled Enable TLS support for FreeRADIUS + ## + enabled: false + ## @param tls.autoGenerated Generate automatically self-signed TLS certificates + ## + autoGenerated: true + autoGenerator: + certmanager: + enabled: false + issuerKind: ClusterIssuer + issuerName: selfsigned-issuer + ## @param tls.certificatesSecret Name of the secret that contains the certificates + ## + certificatesSecret: "" + ## @param tls.certFilename Certificate filename + ## + certFilename: "" + ## @param tls.certKeyFilename Certificate key filename + ## + certKeyFilename: "" + ## @param tls.certCAFilename CA Certificate filename + ## + certCAFilename: "" + + secretName: ~ + existingSecret: "" + +gateway: + enabled: false + dedicated: false + gatewayApi: false + name: "" + namespace: "" + gatewayClassName: istio + ## @param gateway.listeners + ## + listeners: [] + existingGateway: ~ + existingVirtualService: ~ + ## @param gateway.extraRoute Array of extra Kubernetes Gateway API Route to deploy with the release + ## + extraRoute: [] + +## Prometheus exporter configuration +## +metrics: + ## @param metrics.enabled Start a side-car prometheus exporter + ## + enabled: false + ## Bitnami FreeRADIUS Prometheus exporter image + ## ref: + ## @param metrics.image.registry FreeRADIUS Prometheus exporter image registry + ## @param metrics.image.repository FreeRADIUS Prometheus exporter image repository + ## @param metrics.image.tag FreeRADIUS Prometheus exporter image tag (immutable tags are recommended) + ## @param metrics.image.pullPolicy FreeRADIUS Prometheus exporter image pull policy + ## @param metrics.image.pullSecrets FreeRADIUS Prometheus exporter image pull secrets + ## + image: + registry: docker.io + repository: + tag: + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + + ## Prometheus Operator PrometheusRule configuration + ## + prometheusRules: + ## @param metrics.prometheusRules.enabled if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true`, and makes little sense without ServiceMonitor) + ## + enabled: false + ## @param metrics.prometheusRules.additionalLabels [object] Additional labels to add to the PrometheusRule so it is picked up by the operator + ## If using the [Helm Chart](https://github.com/helm/charts/tree/master/stable/prometheus-operator) this is the name of the Helm release and 'app: prometheus-operator' + ## + additionalLabels: + app: prometheus-operator + release: prometheus + ## @param metrics.prometheusRules.rules PrometheusRule rules to configure + ## e.g: + ## - alert: FreeRADIUS-Down + ## annotations: + ## message: 'FreeRADIUS instance {{ $labels.instance }} is down' + ## summary: FreeRADIUS instance is down + ## expr: absent(up{job="freeradius"} == 1) + ## labels: + ## severity: warning + ## service: freeradius + ## for: 5m + ## + rules: {}