diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 0ff1c6d..146a7c5 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -122,6 +122,10 @@ jobs: - name: Verify K3s is running on Server run: docker exec server-node k3s kubectl get nodes | grep Ready + - name: Verify the server config file mode + if: matrix.inventory == 'basic' + run: docker exec server-node ls -l /etc/rancher/k3s/config.yaml | grep -q '^-rw-r-----' + - name: Verify K3s is running on Agent (systemd) if: matrix.service_mgr == 'systemd' run: docker exec agent-node systemctl status k3s-agent | grep running diff --git a/README.md b/README.md index c9bd45b..e901f57 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,16 @@ The `use_external_database` flag is required when more than one server is define The format of the datastore-endpoint parameter is dependent upon the datastore backend, please visit the [K3s datastore endpoint format](https://docs.k3s.io/datastore#datastore-endpoint-format-and-functionality) for details on the format and supported datastores. +### Server config file permissions + +The server role writes `/etc/rancher/k3s/config.yaml` at mode `0644`. That file can contain the cluster token, so any local account on a server node can read the credential that joins a node to the cluster. Set `k3s_server_config_mode` to narrow it: + +```yaml +k3s_server_config_mode: "0640" +``` + +K3s reads the file as root, so `0600` is the safe floor: no other account needs the file. The default stays `0644`, which is the mode the file already has on a running cluster, so a re-run changes nothing until the variable is set. The upgrade role rewrites the same file and honors the same variable. + ## Upgrading A playbook is provided to upgrade K3s on all nodes in the cluster. To use it, update `k3s_version` with the desired version in `inventory.yml` and run one of the following commands. Again, the syntax is slightly different depending on whether you installed `k3s-ansible` with `ansible-galaxy` or if you run the playbook from within the cloned git repository: diff --git a/inventory-sample.yml b/inventory-sample.yml index 189b950..d45b828 100644 --- a/inventory-sample.yml +++ b/inventory-sample.yml @@ -34,6 +34,7 @@ k3s_cluster: # extra_service_envs: [ 'ENV_VAR1=VALUE1', 'ENV_VAR2=VALUE2' ] # user_kubectl: true, by default kubectl is symlinked and configured for use by ansible_user. Set to false to only kubectl via root user. # manage_firewall: false + # k3s_server_config_mode: "0644", mode of /etc/rancher/k3s/config.yaml on server nodes. The file can contain the cluster token; set "0640" to keep it off other local accounts. # Manifests or Airgap should be either full paths or relative to the playbook directory. # List of locally available manifests to apply to the cluster, useful for PVCs or Traefik modifications. diff --git a/roles/k3s_server/defaults/main.yml b/roles/k3s_server/defaults/main.yml index 058aff1..0bcf38a 100644 --- a/roles/k3s_server/defaults/main.yml +++ b/roles/k3s_server/defaults/main.yml @@ -1,5 +1,8 @@ --- k3s_server_location: "/var/lib/rancher/k3s" +# /etc/rancher/k3s/config.yaml can contain the cluster token, so a cluster +# that does not want it world readable can narrow this to "0640". +k3s_server_config_mode: "0644" systemd_dir: "/etc/systemd/system" # noqa var-naming[no-role-prefix] api_port: 6443 # noqa var-naming[no-role-prefix] kubeconfig: ~/.kube/config.new # noqa var-naming[no-role-prefix] diff --git a/roles/k3s_server/tasks/main.yml b/roles/k3s_server/tasks/main.yml index afa4358..aedeefb 100644 --- a/roles/k3s_server/tasks/main.yml +++ b/roles/k3s_server/tasks/main.yml @@ -152,7 +152,7 @@ ansible.builtin.copy: content: "{{ k3s_server_config | to_nice_yaml }}" dest: "/etc/rancher/k3s/config.yaml" - mode: "0644" + mode: "{{ k3s_server_config_mode }}" register: k3s_server_config_result - name: Delete any existing token from the environment if different from the new one @@ -280,7 +280,7 @@ ansible.builtin.copy: content: "{{ k3s_server_config | to_nice_yaml }}" dest: "/etc/rancher/k3s/config.yaml" - mode: "0644" + mode: "{{ k3s_server_config_mode }}" register: k3s_server_config_result - name: Delete any existing token from the environment if different from the new one diff --git a/roles/k3s_upgrade/defaults/main.yml b/roles/k3s_upgrade/defaults/main.yml index 99ae181..6675cc2 100644 --- a/roles/k3s_upgrade/defaults/main.yml +++ b/roles/k3s_upgrade/defaults/main.yml @@ -8,4 +8,5 @@ api_port: 6443 # noqa var-naming[no-role-prefix] extra_server_args: "" # noqa var-naming[no-role-prefix] extra_agent_args: "" # noqa var-naming[no-role-prefix] use_external_database: false # noqa var-naming[no-role-prefix] +k3s_server_config_mode: "0644" # noqa var-naming[no-role-prefix] # api_endpoint must be provided by inventory for agent nodes diff --git a/roles/k3s_upgrade/tasks/main.yml b/roles/k3s_upgrade/tasks/main.yml index 84e55b4..91ca714 100644 --- a/roles/k3s_upgrade/tasks/main.yml +++ b/roles/k3s_upgrade/tasks/main.yml @@ -116,7 +116,7 @@ ansible.builtin.copy: content: "{{ k3s_server_config | to_nice_yaml }}" dest: "/etc/rancher/k3s/config.yaml" - mode: "0644" + mode: "{{ k3s_server_config_mode }}" register: k3s_server_config_result - name: Install new K3s Version [server] diff --git a/tests/basic.yml b/tests/basic.yml index 406141b..7a7f189 100644 --- a/tests/basic.yml +++ b/tests/basic.yml @@ -15,5 +15,7 @@ k3s_cluster: k3s_version: v1.33.4+k3s1 token: "secret12345" api_endpoint: "server-node" + # A mode other than the default, so the templated mode is exercised. + k3s_server_config_mode: "0640" extra_server_args: "--snapshotter=native" extra_agent_args: "--snapshotter=native"