etcd doesn’t actually enforce fine-grained access control based on users and roles out of the box; you have to enable it.

Let’s say you’ve got a multi-tenant Kubernetes cluster, or you’re running sensitive workloads and want to restrict who can do what to your etcd data. You can’t just let anyone with a client certificate poke around. You need to set up authentication and authorization.

Here’s how you’d typically get etcd to start respecting users and roles.

Setting Up TLS for Authentication

First, etcd needs to know who is talking to it. The standard way to do this is with TLS client certificate authentication. This means every client (like your Kubernetes API server) needs a certificate signed by the same Certificate Authority (CA) that etcd trusts.

Let’s assume you’ve got your CA set up. You’ll need to generate a client certificate and key for your etcd server itself, and then for each client that will interact with etcd.

For example, to create a certificate signing request (CSR) for an etcd server:

openssl req -new -key etcd-server.key -out etcd-server.csr -subj "/CN=etcd-server/O=etcd"

And to sign it with your CA:

openssl x509 -req -in etcd-server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out etcd-server.crt -days 365

You’ll do similar steps for your clients, but with different Subject fields, like /CN=kube-apiserver/O=kubernetes.

Then, when you start your etcd server, you’ll point it to these files using flags:

etcd \
  --cert-file=/etc/etcd/ssl/etcd-server.crt \
  --key-file=/etc/etcd/ssl/etcd-server.key \
  --trusted-ca-file=/etc/etcd/ssl/ca.crt \
  # ... other etcd flags

And your clients (like the Kubernetes API server) will use their own kubeconfig files that reference their client certificate, key, and the CA.

Enabling Authorization

Once etcd knows who is talking to it, you need to tell it what they’re allowed to do. This is where the authorization part comes in. etcd supports several authorization modes, but for fine-grained control, you’ll use rwo (read-write-owner) or abac (attribute-based access control). rwo is simpler and often sufficient.

To enable rwo authorization, you’ll pass the --authorization-mode=rwo flag to your etcd server.

Creating Roles and Users

Now for the main event: users and roles. etcd’s built-in role-based access control (RBAC) is managed via its own API. You don’t use Kubernetes RBAC here; you interact directly with etcd.

First, you need a user that has permission to manage etcd users and roles. This is typically the root user that etcd creates by default, which has unrestricted access. You’ll use etcdctl to interact with the etcd API.

Let’s create a new user named app-user and a role named app-role.

1. Create the Role:

This role will define what actions are allowed. Let’s say app-role should be allowed to read and write keys under a specific prefix, like /myapp/data/.

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/ca.crt --cert=/etc/etcd/ssl/root.crt --key=/etc/etcd/ssl/root.key \
  role add app-role --key-prefix '/myapp/data/' --read --write
  • --cacert, --cert, --key: These point to the root user’s credentials for authenticating with etcd.
  • role add app-role: This command adds a new role named app-role.
  • --key-prefix '/myapp/data/': This specifies that the permissions apply only to keys starting with /myapp/data/.
  • --read --write: These grant read and write permissions for the specified key prefix.

2. Create the User:

Now, create the app-user and assign app-role to them.

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/ca.crt --cert=/etc/etcd/ssl/root.crt --key=/etc/etcd/ssl/root.key \
  user add app-user --roles app-role
  • user add app-user: This command adds a new user named app-user.
  • --roles app-role: This assigns the previously created app-role to this user.

By default, when you create a user this way, etcd generates a new certificate for them. You’ll need to retrieve this certificate and key and configure your application or client to use them.

To get the user’s certificate and key:

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/ca.crt --cert=/etc/etcd/ssl/root.crt --key=/etc/etcd/ssl/root.key \
  user get-cert app-user --out-file app-user.crt --out-key-file app-user.key

This will generate app-user.crt and app-user.key which your application will use to authenticate with etcd.

3. Configure Your Application:

Your application (e.g., a custom controller, a specific pod) will need a kubeconfig file (or direct etcd client configuration) that points to:

  • The etcd endpoint.
  • The CA certificate (ca.crt).
  • The newly generated client certificate (app-user.crt).
  • The newly generated client key (app-user.key).

This ensures that when your application connects to etcd, it presents the app-user certificate, and etcd’s authorization layer checks if app-user has permissions via app-role to perform the requested operation on the target key.

What happens under the hood:

When a client connects, etcd first authenticates the client using TLS. If successful, it identifies the user based on the certificate’s Common Name (CN) and Organization (O) fields. Then, it looks up the user’s assigned roles. For each role, it checks the granted permissions against the requested operation (e.g., PUT, GET, DELETE) and the target key. If any role grants the permission, the operation is allowed. If no role grants permission, or if the user has no roles, the operation is denied.

The most surprising thing about etcd’s RBAC is that it’s entirely separate from Kubernetes RBAC. You manage etcd users and roles directly against the etcd cluster, not through Kubernetes Role or RoleBinding objects. This means you need a distinct workflow for securing etcd itself, independent of how you secure access to Kubernetes resources.

The next challenge you’ll likely face is managing the lifecycle of these etcd users and their certificates, especially in dynamic environments.

Want structured learning?

Take the full Etcd course →