Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement mounting user certificates and keys #125

Merged
merged 13 commits into from
Apr 11, 2024
Prev Previous commit
Next Next commit
change mounting spec completely
  • Loading branch information
Kirill-Garbar committed Apr 10, 2024
commit b823d9acd72945dd728599490d9154a3ce3f2737
315 changes: 315 additions & 0 deletions AUTH-DESIGN-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
### Peer.ca
| Option | Description |
| ------ | ----------- |
| secretName | Secret name of user-provided secret. If not specified then operator generates certificate by the spec below |
| metadata | Metadata of generated secret. |
| duration | Expiration time of generated secret. |
| renewBefore | Time period before expiration time when certificate will be reissued. |
| privateKey | Private key configuration: algorithm and key size. |

### Peer.cert
| Option | Description |
| ------ | ----------- |
| secretName | Secret name of user-provided secret. If not specified then operator generates certificate by the spec below. If peer.ca.secretName is provided, then this certificate is generated from the CA that was provided by the user. You can't define the secret name in this section and do not define peer.ca.secretName. |
| metadata | Metadata of generated secret. |
| duration | Expiration time of generated secret. |
| renewBefore | Time period before expiration time when certificate will be reissued. |
| privateKey | Private key configuration: algorithm, key size and boolean parameter is it necessary to rotate private key when certificate is expired |

### ClientServer section has the same fields as peer section.

### Rbac
| Option | Description |
| ------ | ----------- |
| enabled | Enables role-based access control: creates root user in etcd, gives him root role and enables authentication in etcd. |

```yaml
spec:
security:
peer:
enabled: true # optional
ca:
# if not defined, then operator generates CA by the spec below
secretName: ext-peer-ca-tls-secret
secretTemplate:
metadata:
name: peer-ca-tls-secret # optional
annotations: {} # optional
labels: {} # optional
duration: 86400h # optional
renewBefore: 720h # optional
privateKey:
algorithm: RSA # optional
size: 4096 # optional
cert:
secretName: ext-peer-tls-secret
secretTemplate:
metadata:
name: peer-tls-secret # optional
annotations: {} # optional
labels: {} # optional
duration: 720h
renewBefore: 180h
privateKey:
rotate: true # optional
algorithm: RSA
size: 4096
clientServer:
enabled: true
ca:
secretName: ext-server-ca-tls-secret
secretTemplate:
metadata:
name: server-ca-tls-secret
annotations: {} # optional
labels: {} # optional
duration: 86400h
renewBefore: 720h
privateKey:
algorithm: RSA
size: 4096
cert:
secretName: ext-server-tls-secret
secretTemplate:
metadata:
name: server-tls-secret
annotations: {} # optional
labels: {} # optional
extraSans: []
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
rootClientCert:
secretName: ext-client-tls-secret
secretTemplate:
metadata:
name: client-tls-secret
annotations: {} # optional
labels: {} # optional
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
rbac:
enabled: true # optional
```

Important points:
* If field has a value and it is optional, then this value is a default.
* peer:
* If ca.secretName is not defined, operator generates its own CA.
* If ca.secretName is defined, then every field under secretName should not be defined.
* If cert.secretName id not defined, then certificate is generate by operator from the CA defined in the section above (user-managed or operator-managed).
* User must define ca.secretName if cert.secretName is defined.
* Algorithm is a list of the values. NOTE: look into the lib that generates certs what values exist (or to cert-manager).
* clientServer:
* See peer logic.
* RootClientCert uses server ca and has the same logic as server.cert.
* Rbac.enabled enables role-based access control: creates root user in etcd, gives him root role and enables authentication in etcd.



security:
peerCertificate: {}
peerTrustedCACertficate: {}
clientCertificate: {}
serverCertificate: {}
trustedCACertificate: {}

```yaml
spec:
security:
disableClientAuth: false
peerCertificate:
secretName: ext-peer-tls-secret
secretTemplate:
metadata:
name: peer-tls-secret
annotations: {}
labels: {}
duration: 720h
renewBefore: 180h
privateKey:
rotate: true # optional
algorithm: RSA
size: 4096
peerTrustedCaCertficate:
# if not defined, then operator generates CA by the spec below
secretName: ext-peer-ca-tls-secret
secretTemplate:
metadata:
name: peer-ca-tls-secret
annotations: {} # optional
labels: {} # optional
duration: 86400h # optional
renewBefore: 720h # optional
privateKey:
algorithm: RSA # optional
size: 4096 # optional
serverCertificate:
secretName: ext-server-tls-secret
secretTemplate:
metadata:
name: server-tls-secret
annotations: {}
labels: {}
extraClientSans: []
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
trustedCaCertificate:
secretName: ext-server-ca-tls-secret
secretTemplate:
metadata:
name: server-ca-tls-secret
annotations: {}
labels: {}
duration: 86400h
renewBefore: 720h
privateKey:
algorithm: RSA
size: 4096
clientCertificate:
secretName: ext-client-tls-secret
secretTemplate:
metadata:
name: client-tls-secret
annotations: {}
labels: {}
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
```






### Peer.ca
| Option | Description |
| ------ | ----------- |
| secretName | Secret name of user-provided secret. If not specified then operator generates certificate by the spec below |
| metadata | Metadata of generated secret. |
| duration | Expiration time of generated secret. |
| renewBefore | Time period before expiration time when certificate will be reissued. |
| privateKey | Private key configuration: algorithm and key size. |

### Peer.cert
| Option | Description |
| ------ | ----------- |
| secretName | Secret name of user-provided secret. If not specified then operator generates certificate by the spec below. If peer.ca.secretName is provided, then this certificate is generated from the CA that was provided by the user. You can't define the secret name in this section and do not define peer.ca.secretName. |
| metadata | Metadata of generated secret. |
| duration | Expiration time of generated secret. |
| renewBefore | Time period before expiration time when certificate will be reissued. |
| privateKey | Private key configuration: algorithm, key size and boolean parameter is it necessary to rotate private key when certificate is expired |

### ClientServer section has the same fields as peer section.

### Rbac
| Option | Description |
| ------ | ----------- |
| enabled | Enables role-based access control: creates root user in etcd, gives him root role and enables authentication in etcd. |

```yaml
spec:
security:
peer:
enabled: true # optional
ca:
# if not defined, then operator generates CA by the spec below
secretName: ext-peer-ca-tls-secret # oneof secretName or secretTemplate
secretTemplate: # oneof secretName or secretTemplate
annotations: {} # optional
labels: {} # optional
duration: 86400h # optional
renewBefore: 720h # optional
privateKey:
algorithm: RSA # optional
size: 4096 # optional
cert:
secretName: ext-peer-tls-secret
secretTemplate:
annotations: {}
labels: {}
duration: 720h
renewBefore: 180h
privateKey:
rotate: true # optional
algorithm: RSA
size: 4096
server:
enabled: true
ca:
secretName: ext-server-ca-tls-secret
secretTemplate:
annotations: {}
labels: {}
duration: 86400h
renewBefore: 720h
privateKey:
algorithm: RSA
size: 4096
cert:
secretName: ext-server-tls-secret
secretTemplate:
annotations: {}
labels: {}
extraSANs: []
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
client:
enabled: true
ca:
secretName: ext-server-ca-tls-secret
secretTemplate:
annotations: {}
labels: {}
duration: 86400h
renewBefore: 720h
privateKey:
algorithm: RSA
size: 4096
cert:
secretName: ext-client-tls-secret
secretTemplate:
annotations: {}
labels: {}
duration: 720h
renewBefore: 180h
privateKey:
rotate: true
algorithm: RSA
size: 4096
auth:
enabled: true # optional
```

Important points:
* If field has a value and it is optional, then this value is a default.
* peer:
* If ca.secretName is not defined, operator generates its own CA.
* If ca.secretName is defined, then every field under secretName should not be defined.
* If cert.secretName id not defined, then certificate is generate by operator from the CA defined in the section above (user-managed or operator-managed).
* User must define ca.secretName if cert.secretName is defined.
* Algorithm is a list of the values. NOTE: look into the lib that generates certs what values exist (or to cert-manager).
* clientServer:
* See peer logic.
* RootClientCert uses server ca and has the same logic as server.cert.
* Rbac.enabled enables role-based access control: creates root user in etcd, gives him root role and enables authentication in etcd.

37 changes: 15 additions & 22 deletions api/v1alpha1/etcdcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,36 +206,29 @@ type StorageSpec struct {
// SecuritySpec defines security settings for etcd.
// +k8s:openapi-gen=true
type SecuritySpec struct {
// Section for user-managed tls certificates
// +optional
Peer *PeerSpec `json:"peer,omitempty"`
// +optional
ClientServer *ClientServerSpec `json:"clientServer,omitempty"`
TLS TLSSpec `json:"tls,omitempty"`
}

type PeerSpec struct {
// TLSSpec defines user-managed certificates names.
type TLSSpec struct {
// Trusted CA certificate secret to secure peer-to-peer communication between etcd nodes. It is expected to have tls.crt field in the secret.
// +optional
Ca SecretSpec `json:"ca,omitempty"`
PeerTrustedCASecret string `json:"peerTrustedCASecret,omitempty"`
// Certificate secret to secure peer-to-peer communication between etcd nodes. It is expected to have tls.crt and tls.key fields in the secret.
// +optional
Cert SecretSpec `json:"cert,omitempty"`
}

type ClientServerSpec struct {
PeerSecret string `json:"peerSecret,omitempty"`
// Server certificate secret to secure client-server communication. Is provided to the client who connects to etcd by client port (2379 by default).
// It is expected to have tls.crt and tls.key fields in the secret.
// +optional
Ca SecretSpec `json:"ca,omitempty"`
ServerSecret string `json:"serverSecret,omitempty"`
// Trusted CA for client certificates that are provided by client to etcd. It is expected to have tls.crt field in the secret.
// +optional
ServerCert SecretSpec `json:"serverCert,omitempty"`
// +optional
RootClientCert SecretSpec `json:"rootClientCert,omitempty"`
}

type SecretSpec struct {
// +optional
SecretName string `json:"secretName,omitempty"`
}

type RbacSpec struct {
ClientTrustedCASecret string `json:"clientTrustedCASecret,omitempty"`
// Client certificate for etcd-operator to do maintenance. It is expected to have tls.crt and tls.key fields in the secret.
// +optional
Enabled bool `json:"enabled,omitempty"`
ClientSecret string `json:"clientSecret,omitempty"`
}

// EmbeddedPersistentVolumeClaim is an embedded version of k8s.io/api/core/v1.PersistentVolumeClaim.
Expand Down
Loading
Loading