Skip to content

Commit b393470

Browse files
authored
Merge pull request #1716 from stgraber/ceph
incusd/storage/ceph: Re-introduce keyring parsing
2 parents 4905664 + 7de13bd commit b393470

File tree

1 file changed

+118
-16
lines changed

1 file changed

+118
-16
lines changed

internal/server/storage/drivers/utils_ceph.go

+118-16
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package drivers
22

33
import (
4+
"bufio"
45
"encoding/json"
56
"fmt"
7+
"os"
68
"strings"
79

810
"github.com/lxc/incus/v6/shared/api"
911
"github.com/lxc/incus/v6/shared/logger"
1012
"github.com/lxc/incus/v6/shared/subprocess"
13+
"github.com/lxc/incus/v6/shared/util"
1114
)
1215

1316
// CephGetRBDImageName returns the RBD image name as it is used in ceph.
@@ -182,21 +185,21 @@ func CephMonitors(cluster string) (Monitors, error) {
182185

183186
// CephKeyring retrieves the CephX key for the given entity.
184187
func CephKeyring(cluster string, client string) (string, error) {
188+
// See if we can't find it from the filesystem directly (short path).
189+
value, err := cephKeyringFromFile(cluster, client)
190+
if err == nil {
191+
return value, nil
192+
}
193+
185194
// If client isn't prefixed, prefix it with 'client.'.
186195
if !strings.Contains(client, ".") {
187196
client = "client." + client
188197
}
189198

190199
// Check that cephx is enabled.
191-
authType, err := callCeph(
192-
"--cluster", cluster,
193-
"config", "get", client, "auth_service_required",
194-
)
200+
authType, err := callCeph("--cluster", cluster, "config", "get", client, "auth_service_required")
195201
if err != nil {
196-
return "", fmt.Errorf(
197-
"Failed to query ceph config for auth_service_required: %w",
198-
err,
199-
)
202+
return "", fmt.Errorf("Failed to query ceph config for auth_service_required: %w", err)
200203
}
201204

202205
if authType == "none" {
@@ -208,20 +211,119 @@ func CephKeyring(cluster string, client string) (string, error) {
208211
key := struct {
209212
Key string `json:"key"`
210213
}{}
211-
err = callCephJSON(&key,
212-
"--cluster", cluster,
213-
"auth", "get-key", client,
214-
)
214+
err = callCephJSON(&key, "--cluster", cluster, "auth", "get-key", client)
215215
if err != nil {
216-
return "", fmt.Errorf(
217-
"Failed to get keyring for %q on %q: %w",
218-
client, cluster, err,
219-
)
216+
return "", fmt.Errorf("Failed to get keyring for %q on %q: %w", client, cluster, err)
220217
}
221218

222219
return key.Key, nil
223220
}
224221

222+
func cephGetKeyFromFile(path string) (string, error) {
223+
cephKeyring, err := os.Open(path)
224+
if err != nil {
225+
return "", fmt.Errorf("Failed to open %q: %w", path, err)
226+
}
227+
228+
// Locate the keyring entry and its value.
229+
var cephSecret string
230+
scan := bufio.NewScanner(cephKeyring)
231+
for scan.Scan() {
232+
line := scan.Text()
233+
line = strings.TrimSpace(line)
234+
235+
if line == "" {
236+
continue
237+
}
238+
239+
if strings.HasPrefix(line, "key") {
240+
fields := strings.SplitN(line, "=", 2)
241+
if len(fields) < 2 {
242+
continue
243+
}
244+
245+
cephSecret = strings.TrimSpace(fields[1])
246+
break
247+
}
248+
}
249+
250+
if cephSecret == "" {
251+
return "", fmt.Errorf("Couldn't find a keyring entry")
252+
}
253+
254+
return cephSecret, nil
255+
}
256+
257+
// cephKeyringFromFile gets the key for a particular Ceph cluster and client name.
258+
func cephKeyringFromFile(cluster string, client string) (string, error) {
259+
var cephSecret string
260+
cephConfigPath := fmt.Sprintf("/etc/ceph/%v.conf", cluster)
261+
262+
keyringPathFull := fmt.Sprintf("/etc/ceph/%v.client.%v.keyring", cluster, client)
263+
keyringPathCluster := fmt.Sprintf("/etc/ceph/%v.keyring", cluster)
264+
keyringPathGlobal := "/etc/ceph/keyring"
265+
keyringPathGlobalBin := "/etc/ceph/keyring.bin"
266+
267+
if util.PathExists(keyringPathFull) {
268+
return cephGetKeyFromFile(keyringPathFull)
269+
} else if util.PathExists(keyringPathCluster) {
270+
return cephGetKeyFromFile(keyringPathCluster)
271+
} else if util.PathExists(keyringPathGlobal) {
272+
return cephGetKeyFromFile(keyringPathGlobal)
273+
} else if util.PathExists(keyringPathGlobalBin) {
274+
return cephGetKeyFromFile(keyringPathGlobalBin)
275+
} else if util.PathExists(cephConfigPath) {
276+
// Open the CEPH config file.
277+
cephConfig, err := os.Open(cephConfigPath)
278+
if err != nil {
279+
return "", fmt.Errorf("Failed to open %q: %w", cephConfigPath, err)
280+
}
281+
282+
// Locate the keyring entry and its value.
283+
scan := bufio.NewScanner(cephConfig)
284+
for scan.Scan() {
285+
line := scan.Text()
286+
line = strings.TrimSpace(line)
287+
288+
if line == "" {
289+
continue
290+
}
291+
292+
if strings.HasPrefix(line, "key") {
293+
fields := strings.SplitN(line, "=", 2)
294+
if len(fields) < 2 {
295+
continue
296+
}
297+
298+
// Check all key related config keys.
299+
switch strings.TrimSpace(fields[0]) {
300+
case "key":
301+
cephSecret = strings.TrimSpace(fields[1])
302+
case "keyfile":
303+
key, err := os.ReadFile(fields[1])
304+
if err != nil {
305+
return "", err
306+
}
307+
308+
cephSecret = strings.TrimSpace(string(key))
309+
case "keyring":
310+
return cephGetKeyFromFile(strings.TrimSpace(fields[1]))
311+
}
312+
}
313+
314+
if cephSecret != "" {
315+
break
316+
}
317+
}
318+
}
319+
320+
if cephSecret == "" {
321+
return "", fmt.Errorf("Couldn't find a keyring entry")
322+
}
323+
324+
return cephSecret, nil
325+
}
326+
225327
// CephFsid retrieves the FSID for the given cluster.
226328
func CephFsid(cluster string) (string, error) {
227329
// Call ceph fsid.

0 commit comments

Comments
 (0)