Skip to content

Commit

Permalink
Cluster: Enforce member name cannot be none (#13963)
Browse files Browse the repository at this point in the history
In #13957 (comment) we
found that currently `none` is a valid LXD cluster member name.

This collides with the internally used concept which identifies if LXD
is clustered or not by setting it's internal `ServerName` to `none` or
it's actual cluster name.

The PR ensures that a LXD cluster member's name cannot be `none` as well
as blocking the creation of join tokens with name `none`.
  • Loading branch information
tomponline authored Aug 22, 2024
2 parents e7b2a7a + c49ef5f commit 59ad83c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lxd/api_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ func clusterPut(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(fmt.Errorf("ServerName may not start with %q", targetGroupPrefix))
}

if req.ServerName == "none" {
return response.BadRequest(fmt.Errorf("ServerName cannot be %q", req.ServerName))
}

// Disable clustering.
if !req.Enabled {
return clusterPutDisable(d, r, req)
Expand Down Expand Up @@ -1329,6 +1333,10 @@ func clusterNodesPost(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(fmt.Errorf("This server is not clustered"))
}

if req.ServerName == "none" {
return response.BadRequest(fmt.Errorf("Join token name cannot be %q", req.ServerName))
}

expiry, err := shared.GetExpiry(time.Now(), s.GlobalConfig.ClusterJoinTokenExpiry())
if err != nil {
return response.BadRequest(err)
Expand Down
14 changes: 14 additions & 0 deletions test/suites/clustering.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,20 @@ test_clustering_join_api() {
ns2="${prefix}2"
LXD_NETNS="${ns2}" spawn_lxd "${LXD_TWO_DIR}" false

# Check a join token cannot be created for the reserved name 'none'
! lxc cluster add none --quiet || false

# Check a server with the name 'valid' cannot be joined when modifying the token.
# Therefore replace the valid name in the token with 'none'.
malicious_token="$(lxc cluster add valid --quiet | base64 -d | jq '.server_name |= "none"' | base64 --wrap=0)"
op=$(curl --unix-socket "${LXD_TWO_DIR}/unix.socket" -X PUT "lxd/1.0/cluster" -d "{\"server_name\":\"valid\",\"enabled\":true,\"member_config\":[{\"entity\": \"storage-pool\",\"name\":\"data\",\"key\":\"source\",\"value\":\"\"}],\"server_address\":\"10.1.1.102:8443\",\"cluster_address\":\"10.1.1.101:8443\",\"cluster_certificate\":\"${cert}\",\"cluster_token\":\"${malicious_token}\"}" | jq -r .operation)
[ "$(curl --unix-socket "${LXD_TWO_DIR}/unix.socket" "lxd${op}/wait" | jq '.error_code')" = "403" ]

# Check that the server cannot be joined using a valid token by changing it's name to 'none'.
token="$(lxc cluster add valid2 --quiet)"
[ "$(curl --unix-socket "${LXD_TWO_DIR}/unix.socket" -X PUT "lxd/1.0/cluster" -d "{\"server_name\":\"none\",\"enabled\":true,\"member_config\":[{\"entity\": \"storage-pool\",\"name\":\"data\",\"key\":\"source\",\"value\":\"\"}],\"server_address\":\"10.1.1.102:8443\",\"cluster_address\":\"10.1.1.101:8443\",\"cluster_certificate\":\"${cert}\",\"cluster_token\":\"${token}\"}" | jq -r '.error_code')" = "400" ]

# Check the server can be joined.
token="$(lxc cluster add node2 --quiet)"
op=$(curl --unix-socket "${LXD_TWO_DIR}/unix.socket" -X PUT "lxd/1.0/cluster" -d "{\"server_name\":\"node2\",\"enabled\":true,\"member_config\":[{\"entity\": \"storage-pool\",\"name\":\"data\",\"key\":\"source\",\"value\":\"\"}],\"server_address\":\"10.1.1.102:8443\",\"cluster_address\":\"10.1.1.101:8443\",\"cluster_certificate\":\"${cert}\",\"cluster_token\":\"${token}\"}" | jq -r .operation)
curl --unix-socket "${LXD_TWO_DIR}/unix.socket" "lxd${op}/wait"
Expand Down

0 comments on commit 59ad83c

Please sign in to comment.