Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

feat: Add user configuration for all providers #4

Merged
merged 13 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions api/v1alpha1/clusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ type GenericClusterConfig struct {

// +optional
Addons *Addons `json:"addons,omitempty"`

// +optional
Users Users `json:"users,omitempty"`
}

func (s GenericClusterConfig) VariableSchema() clusterv1.VariableSchema { //nolint:gocritic,lll // Passed by value for no potential side-effect.
Expand All @@ -116,6 +119,7 @@ func (s GenericClusterConfig) VariableSchema() clusterv1.VariableSchema { //noli
OpenAPIV3Schema,
"imageRegistries": ImageRegistries{}.VariableSchema().OpenAPIV3Schema,
"globalImageRegistryMirror": GlobalImageRegistryMirror{}.VariableSchema().OpenAPIV3Schema,
"users": Users{}.VariableSchema().OpenAPIV3Schema,
},
},
}
Expand Down Expand Up @@ -344,6 +348,83 @@ func (ImageRegistries) VariableSchema() clusterv1.VariableSchema {
}
}

type Users []User

func (Users) VariableSchema() clusterv1.VariableSchema {
return clusterv1.VariableSchema{
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
Description: "Users to add to the machine",
Type: "array",
Items: ptr.To(User{}.VariableSchema().OpenAPIV3Schema),
},
}
}

// User defines the input for a generated user in cloud-init.
type User struct {
// Name specifies the user name.
Name string `json:"name"`

// HashedPassword is a hashed password for the user, formatted as described
// by the crypt(5) man page. See your distribution's documentation for
// instructions to create a hashed password.
// An empty string is not marshalled, because it is not a valid value.
// +optional
HashedPassword string `json:"hashedPassword,omitempty"`

// SSHAuthorizedKeys is a list of public SSH keys to write to the
// machine. Use the corresponding private SSH keys to authenticate. See SSH
// documentation for instructions to create a key pair.
// +optional
SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"`

// Sudo is a sudo user specification, formatted as described in the sudo
// documentation.
// An empty string is not marshalled, because it is not a valid value.
// +optional
Sudo string `json:"sudo,omitempty"`
}

func (User) VariableSchema() clusterv1.VariableSchema {
return clusterv1.VariableSchema{
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
Type: "object",
Required: []string{"name"},
Properties: map[string]clusterv1.JSONSchemaProps{
"name": {
Description: "The username",
Type: "string",
},
"hashedPassword": {
Description: "The hashed password for the user. Must be in the format of some hash function supported by the OS.",
Type: "string",
// The crypt (5) man page lists regexes for supported hash
// functions. We could validate input against a set of
// regexes, but because the set may be different from the
// set supported by the chosen OS, we might return a false
// negative or positive. For this reason, we do not validate
// the input.
},
"sshAuthorizedKeys": {
Description: "A list of SSH authorized keys for this user",
Type: "array",
Items: &clusterv1.JSONSchemaProps{
// No description, because the one for the parent array is enough.
Type: "string",
},
},
"sudo": {
Description: "The sudo rule that applies to this user",
Type: "string",
// A sudo rule is defined using an EBNF grammar, and must be
// parsed to be validated. We have decided to not integrate
// a sudo rule parser, so we do not validate the input.
},
},
},
}
}

func init() {
SchemeBuilder.Register(&ClusterConfig{})
}
48 changes: 48 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions docs/content/customization/generic/users.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
+++
title = "Users"
+++

Configure users for all machines in the cluster, the user's superuser capabilities using `sudo` user specifications, and
the login authentication mechanism.

> - SSH _authorized keys_ are just public SSH keys that are used to authenticate a login. See the [SSH man
> page](https://www.man7.org/linux/man-pages/man8/sshd.8.html#AUTHORIZED_KEYS_FILE_FORMAT) for more information.
>
> - For information on sudo user specifications, see the [sudo
> documentation](https://www.sudo.ws/docs/man/sudoers.man/#User_specification).
>
> - Local password authentication is disabled for the user by default. It is enabled only when a hashed password is
> provided.

## Examples

### Admin user with SSH public key login

Creates a user with the name `admin`, grants the user the ability to run any command as the superuser, and allows you to
login via SSH using the username and private key corresponding to the authorized public key.

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <NAME>
spec:
topology:
variables:
- name: clusterConfig
value:
users:
- name: admin
- sshAuthorizedKeys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAua0lo8BiGWgvIiDCKnQDKL5uERHfnehm0ns5CEJpJw optionalcomment"
sudo: "ALL=(ALL) NOPASSWD:ALL"
```

### Admin user with serial console password login

Creates a user with the name `admin,` grants the user the ability to run any command as the superuser, and allows you to
login via serial console using the username and password.

> Note that this does not allow you to login via SSH using the username and password; in most cases, you must also
> configure the SSH server to allow password authentication.

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <NAME>
spec:
topology:
variables:
- name: clusterConfig
value:
users:
- name: admin
hashedPassword: "$y$j9T$UraH8eN4XvapXBmmSaUrP0$Nyxdf1cJDGZcp0WDKu.CFHprrkPG4ubirqSqiD43Ix3"
sudo: "ALL=(ALL) NOPASSWD:ALL"
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api v0.0.0-00010101000000-000000000000
github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common v0.0.0-00010101000000-000000000000
github.com/go-logr/logr v1.4.1
github.com/google/go-cmp v0.6.0
github.com/onsi/ginkgo/v2 v2.16.0
github.com/onsi/gomega v1.31.1
github.com/spf13/pflag v1.0.5
Expand Down Expand Up @@ -71,7 +72,6 @@ require (
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-github/v53 v53.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
Expand Down
9 changes: 9 additions & 0 deletions pkg/handlers/aws/mutation/metapatch_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
kubernetesimagerepositorytests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/kubernetesimagerepository/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors"
globalimageregistrymirrortests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/users"
userstests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/users/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/workerconfig"
)

Expand Down Expand Up @@ -188,4 +190,11 @@ func TestGeneratePatches(t *testing.T) {
v1alpha1.AWSVariableName,
controlplaneloadbalancer.VariableName,
)

userstests.TestGeneratePatches(
t,
metaPatchGeneratorFunc(mgr),
clusterconfig.MetaVariableName,
users.VariableName,
)
}
9 changes: 9 additions & 0 deletions pkg/handlers/docker/mutation/metapatch_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
kubernetesimagerepositorytests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/kubernetesimagerepository/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors"
globalimageregistrymirrortests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/users"
userstests "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/users/tests"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/workerconfig"
)

Expand Down Expand Up @@ -112,4 +114,11 @@ func TestGeneratePatches(t *testing.T) {
clusterconfig.MetaVariableName,
mirrors.GlobalMirrorVariableName,
)

userstests.TestGeneratePatches(
t,
metaPatchGeneratorFunc(mgr),
clusterconfig.MetaVariableName,
users.VariableName,
)
}
2 changes: 2 additions & 0 deletions pkg/handlers/generic/mutation/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/imageregistries/credentials"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/kubernetesimagerepository"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/users"
)

// MetaMutators returns all generic patch handlers.
Expand All @@ -28,5 +29,6 @@ func MetaMutators(mgr manager.Manager) []mutation.MetaMutator {
credentials.NewPatch(mgr.GetClient()),
mirrors.NewPatch(mgr.GetClient()),
calico.NewPatch(),
users.NewPatch(),
}
}
4 changes: 4 additions & 0 deletions pkg/handlers/generic/mutation/users/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package users
Loading