Richard W.M. Jones
2014-Nov-02 12:46 UTC
[Libguestfs] [PATCH] customize: Add --ssh-inject option for injecting SSH keys.
This adds a customize option: virt-customize --ssh-inject USER[=KEY] virt-builder --ssh-inject USER[=KEY] virt-sysprep --ssh-inject USER[=KEY] In each case this either injects the current (host) user's ssh pubkey into the guest user USER (adding it to ~USER/.ssh/authorized_keys in the guest), or you can specify a particular key. For example: virt-builder fedora-20 --ssh-inject root will add the local user's ssh pubkey into the root account of the newly created guest. Or: virt-customize -a disk.img \ --ssh-inject 'mary=ssh-rsa AAAA.... mary at localhost' adds the given ssh pubkey to mary's account in the guest. This doesn't set the SELinux labels correctly on newly created files and directories, so you have to use --selinux-relabel (probably we should fix this as part of the general effort to fix SELinux relabelling). However it should preserve the labels if the ~/.ssh/authorized_keys file already exists. --- builder/cmdline.ml | 4 +-- customize/customize_run.ml | 81 ++++++++++++++++++++++++++++++++++++++++++++++ generator/customize.ml | 18 +++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/builder/cmdline.ml b/builder/cmdline.ml index c0584f7..e21d5bb 100644 --- a/builder/cmdline.ml +++ b/builder/cmdline.ml @@ -306,8 +306,8 @@ read the man page virt-builder(1). | `Command _ | `InstallPackages _ | `Script _ | `Update -> true | `Delete _ | `Edit _ | `FirstbootCommand _ | `FirstbootPackages _ | `FirstbootScript _ | `Hostname _ | `Link _ | `Mkdir _ - | `Password _ | `RootPassword _ | `Scrub _ | `Timezone _ | `Upload _ - | `Write _ | `Chmod _ -> false + | `Password _ | `RootPassword _ | `Scrub _ | `SSHInject _ + | `Timezone _ | `Upload _ | `Write _ | `Chmod _ -> false ) ops.ops in if requires_execute_on_guest then error (f_"sorry, cannot run commands on a guest with a different architecture"); diff --git a/customize/customize_run.ml b/customize/customize_run.ml index 51b218a..099d611 100644 --- a/customize/customize_run.ml +++ b/customize/customize_run.ml @@ -135,6 +135,81 @@ exec >>%s 2>&1 error (f_"sorry, don't know how to use --update with the '%s' package manager") pm in + (* Find the local [on the host] user's SSH public key. See + * ssh-copy-id(1) default_ID_file for rationale. + *) + let pubkey_re = Str.regexp "^id.*\\.pub$" in + let pubkey_ignore_re = Str.regexp ".*-cert\\.pub$" in + + let local_user_ssh_pubkey () + let home_dir + try getenv "HOME" + with Not_found -> + error (f_"ssh-inject: $HOME environment variable is not set") in + let ssh_dir = home_dir // ".ssh" in + let files = Sys.readdir ssh_dir in + let files = Array.to_list files in + let files = List.filter ( + fun file -> + Str.string_match pubkey_re file 0 && + not (Str.string_match pubkey_ignore_re file 0) + ) files in + if files = [] then + error (f_"ssh-inject: no public key file found in %s") ssh_dir; + + (* Newest file. *) + let files = List.map ( + fun file -> + let file = ssh_dir // file in + let stat = stat file in + (file, stat.st_mtime) + ) files in + let files = List.sort (fun (_,m1) (_,m2) -> compare m2 m1) files in + let newest_file = fst (List.hd files) in + + (* Read and return the public key. *) + let key = read_whole_file newest_file in + if key = "" then + error (f_"ssh-inject: public key file (%s) is empty") newest_file; + + key + + (* Inject SSH key, where possible. *) + and do_ssh_inject username key + match g#inspect_get_type root with + | "linux" | "freebsd" | "netbsd" | "openbsd" | "hurd" -> + (* If the key doesn't have \n at the end, add it. *) + let len = String.length key in + if len < 1 then + error (f_"ssh-inject: key is an empty string"); + let key = if key.[len-1] = '\n' then key else key ^ "\n" in + + (* Get user's home directory. *) + g#aug_init "/" 0; + let expr = sprintf "/files/etc/passwd/%s/home" username in + let home_dir = g#aug_get expr in + g#aug_close (); + + (* Create ~user/.ssh if it doesn't exist. *) + let ssh_dir = sprintf "%s/.ssh" home_dir in + if not (g#exists ssh_dir) then ( + g#mkdir ssh_dir; + g#chmod 0o755 ssh_dir + ); + + (* Create ~user/.ssh/authorized_keys if it doesn't exist. *) + let auth_keys = sprintf "%s/authorized_keys" ssh_dir in + if not (g#exists auth_keys) then ( + g#touch auth_keys; + g#chmod 0o644 auth_keys + ); + + (* Append the key. *) + g#write_append auth_keys key + | typ -> + warning (f_"don't know how to inject SSH keys into %s guests") typ + in + (* Set the random seed. *) msg (f_"Setting a random seed"); if not (Random_seed.set_random_seed g root) then @@ -232,6 +307,12 @@ exec >>%s 2>&1 msg (f_"Scrubbing: %s") path; g#scrub_file path + | `SSHInject user_key -> + let user, key = string_split "=" user_key in + let key = if key = "" then local_user_ssh_pubkey () else key in + msg (f_"SSH key inject: %s") user; + do_ssh_inject user key + | `Timezone tz -> msg (f_"Setting the timezone: %s") tz; if not (Timezone.set_timezone g root tz) then diff --git a/generator/customize.ml b/generator/customize.ml index 8642a54..ef91b62 100644 --- a/generator/customize.ml +++ b/generator/customize.ml @@ -260,6 +260,24 @@ It cannot delete directories, only regular files. =back"; }; + { op_name = "ssh-inject"; + op_type = String "USER[=KEY]"; + op_discrim = "`SSHInject"; + op_shortdesc = "Inject a public key into the guest"; + op_pod_longdesc = "\ +Inject an ssh key so the given C<USER> will be able to log in over +ssh without supplying a password. + +If just I<--ssh-inject> C<USER> is given then we look in the I<current> +user's C<~/.ssh> directory to find the default public ID file. That +key is uploaded. + +You can also upload a specific key using I<--ssh-inject> C<\"USER=KEY\"> + +In either case, this will create the C<~USER/.ssh> directory if required, +and create or append the key to C<~USER/.ssh/authorized_keys>" + }; + { op_name = "timezone"; op_type = String "TIMEZONE"; op_discrim = "`Timezone"; -- 2.0.4
Pino Toscano
2014-Nov-03 11:09 UTC
[Libguestfs] [PATCH] customize: Add --ssh-inject option for injecting SSH keys.
On Sunday 02 November 2014 12:46:40 Richard W.M. Jones wrote:> This adds a customize option: > > virt-customize --ssh-inject USER[=KEY] > virt-builder --ssh-inject USER[=KEY] > virt-sysprep --ssh-inject USER[=KEY] > > In each case this either injects the current (host) user's ssh pubkey > into the guest user USER (adding it to ~USER/.ssh/authorized_keys in > the guest), or you can specify a particular key. > > For example: > > virt-builder fedora-20 --ssh-inject root > > will add the local user's ssh pubkey into the root account of the > newly created guest. Or: > > virt-customize -a disk.img \ > --ssh-inject 'mary=ssh-rsa AAAA.... mary at localhost' > > adds the given ssh pubkey to mary's account in the guest.I like the idea of this patch, I have just a couple of notes.> + (* Find the local [on the host] user's SSH public key. See > + * ssh-copy-id(1) default_ID_file for rationale. > + *) > + let pubkey_re = Str.regexp "^id.*\\.pub$" in > + let pubkey_ignore_re = Str.regexp ".*-cert\\.pub$" in > + > [...] > + let files = Sys.readdir ssh_dir in > + let files = Array.to_list files in > + let files = List.filter ( > + fun file -> > + Str.string_match pubkey_re file 0 && > + not (Str.string_match pubkey_ignore_re file 0) > + ) files inSmall niptick: this might as well not use regexp. Also, it seems to handle either the most recent id*.pub key of the user, or a key specified as string. What about using a selector syntax for --ssh-inject, so: --ssh-inject USER <- recent id*.pub key --ssh-inject "USER:string:ssh-rsa AAAA.... user at localhost" <- string --ssh-inject USER:file:somekey.pub <- stored in a .pub file I can do the changes above, in case. Thanks, -- Pino Toscano
Pino Toscano
2014-Nov-03 18:36 UTC
[Libguestfs] [PATCH] customize: Add --ssh-inject option for injecting SSH keys.
This adds a customize option: virt-customize --ssh-inject USER virt-customize --ssh-inject USER:string:KEY_STRING virt-customize --ssh-inject USER:file:FILENAME (ditto for virt-builder and virt-sysprep) In each case this injects into the guest user USER a) the current (host) user's ssh pubkey b) the key specified as KEY_STRING c) the key in FILENAME adding it to ~USER/.ssh/authorized_keys in the guest. For example: virt-builder fedora-20 --ssh-inject root will add the local user's ssh pubkey into the root account of the newly created guest. Or: virt-customize -a disk.img \ --ssh-inject 'mary:string:ssh-rsa AAAA.... mary at localhost' adds the given ssh pubkey to mary's account in the guest. This doesn't set the SELinux labels correctly on newly created files and directories, so you have to use --selinux-relabel (probably we should fix this as part of the general effort to fix SELinux relabelling). However it should preserve the labels if the ~/.ssh/authorized_keys file already exists. Most of this work is based on a patch sent to the mailing list by Richard W.M. Jones <rjones at redhat.com>: https://www.redhat.com/archives/libguestfs/2014-November/msg00000.html --- builder/Makefile.am | 1 + builder/cmdline.ml | 4 +- builder/virt-builder.pod | 31 +++++++++++ customize/Makefile.am | 3 + customize/customize_run.ml | 8 +++ customize/ssh_key.ml | 133 +++++++++++++++++++++++++++++++++++++++++++++ customize/ssh_key.mli | 31 +++++++++++ generator/customize.ml | 38 ++++++++++++- po/POTFILES-ml | 1 + sysprep/Makefile.am | 1 + v2v/Makefile.am | 1 + 11 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 customize/ssh_key.ml create mode 100644 customize/ssh_key.mli diff --git a/builder/Makefile.am b/builder/Makefile.am index 414279f..206abce 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -111,6 +111,7 @@ deps = \ $(top_builddir)/customize/crypt-c.o \ $(top_builddir)/customize/crypt.cmx \ $(top_builddir)/customize/password.cmx \ + $(top_builddir)/customize/ssh_key.cmx \ $(top_builddir)/customize/customize_cmdline.cmx \ $(top_builddir)/customize/customize_run.cmx \ $(top_builddir)/fish/guestfish-uri.o \ diff --git a/builder/cmdline.ml b/builder/cmdline.ml index c0584f7..e21d5bb 100644 --- a/builder/cmdline.ml +++ b/builder/cmdline.ml @@ -306,8 +306,8 @@ read the man page virt-builder(1). | `Command _ | `InstallPackages _ | `Script _ | `Update -> true | `Delete _ | `Edit _ | `FirstbootCommand _ | `FirstbootPackages _ | `FirstbootScript _ | `Hostname _ | `Link _ | `Mkdir _ - | `Password _ | `RootPassword _ | `Scrub _ | `Timezone _ | `Upload _ - | `Write _ | `Chmod _ -> false + | `Password _ | `RootPassword _ | `Scrub _ | `SSHInject _ + | `Timezone _ | `Upload _ | `Write _ | `Chmod _ -> false ) ops.ops in if requires_execute_on_guest then error (f_"sorry, cannot run commands on a guest with a different architecture"); diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod index 993e92c..82533d6 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -774,6 +774,37 @@ If C</tmp> or C<C:\Temp> is missing. If you don't want the log file to appear in the final image, then use the I<--no-logfile> command line option. +=head2 SSH KEYS + +The I<--ssh-inject> option is used to inject ssh keys for users in +the guest, so they can login without supplying a password. + +The C<SELECTOR> part of the option value is optional; in this case, +I<--ssh-inject> C<USER> means that we look in the I<current> +user's C<~/.ssh> directory to find the default public ID file. That +key is uploaded. "default public ID" is the I<default_ID_file> file +described in L<ssh-copy-id(1)>. + +If specified, the C<SELECTOR> can be in one of the following formats: + +=over 4 + +=item B<--ssh-inject> USER:file:FILENAME + +Read the ssh key from C<FILENAME>. C<FILENAME> is usually a I<.pub> +file. + +=item B<--ssh-inject> USER:string:KEY_STRING + +Use the specified C<KEY_STRING>. C<KEY_STRING> is usually a public +string like I<ssh-rsa AAAA.... user at localhost>. + +=back + +In any case, the C<~USER/.ssh> directory and the +C<~USER/.ssh/authorized_keys> file will be created if not existing +already. + =head2 INSTALLATION PROCESS When you invoke virt-builder, installation proceeds as follows: diff --git a/customize/Makefile.am b/customize/Makefile.am index 60e2091..56c5ad5 100644 --- a/customize/Makefile.am +++ b/customize/Makefile.am @@ -55,6 +55,8 @@ SOURCES = \ perl_edit.mli \ random_seed.ml \ random_seed.mli \ + ssh_key.ml \ + ssh_key.mli \ timezone.ml \ timezone.mli \ urandom.ml \ @@ -92,6 +94,7 @@ ocaml_modules = \ password \ perl_edit \ random_seed \ + ssh_key \ timezone \ customize_cmdline \ customize_run \ diff --git a/customize/customize_run.ml b/customize/customize_run.ml index 51b218a..09ada7d 100644 --- a/customize/customize_run.ml +++ b/customize/customize_run.ml @@ -232,6 +232,14 @@ exec >>%s 2>&1 msg (f_"Scrubbing: %s") path; g#scrub_file path + | `SSHInject (user, selector) -> + (match g#inspect_get_type root with + | "linux" | "freebsd" | "netbsd" | "openbsd" | "hurd" -> + msg (f_"SSH key inject: %s") user; + Ssh_key.do_ssh_inject_unix g user selector + | _ -> + warning (f_"SSH key could be injected for this type of guest")) + | `Timezone tz -> msg (f_"Setting the timezone: %s") tz; if not (Timezone.set_timezone g root tz) then diff --git a/customize/ssh_key.ml b/customize/ssh_key.ml new file mode 100644 index 0000000..09664bf --- /dev/null +++ b/customize/ssh_key.ml @@ -0,0 +1,133 @@ +(* virt-customize + * Copyright (C) 2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +open Common_gettext.Gettext +open Common_utils + +open Customize_utils + +open Printf +open Sys +open Unix + +module G = Guestfs + +type ssh_key_selector +| SystemKey +| KeyFile of string +| KeyString of string + +let rec parse_selector arg + parse_selector_list arg (string_nsplit ":" arg) + +and parse_selector_list orig_arg = function + | [] | [ "" ] -> + SystemKey + | [ "file"; f ] -> + KeyFile f + | [ "string"; s ] -> + KeyString s + | _ -> + error (f_"invalid ssh-inject selector '%s'; see the man page") orig_arg + +(* Find the local [on the host] user's SSH public key. See + * ssh-copy-id(1) default_ID_file for rationale. + *) +let pubkey_re = Str.regexp "^id.*\\.pub$" +let pubkey_ignore_re = Str.regexp ".*-cert\\.pub$" + +let local_user_ssh_pubkey () + let home_dir + try getenv "HOME" + with Not_found -> + error (f_"ssh-inject: $HOME environment variable is not set") in + let ssh_dir = home_dir // ".ssh" in + let files = Sys.readdir ssh_dir in + let files = Array.to_list files in + let files = List.filter ( + fun file -> + Str.string_match pubkey_re file 0 && + not (Str.string_match pubkey_ignore_re file 0) + ) files in + if files = [] then + error (f_"ssh-inject: no public key file found in %s") ssh_dir; + + (* Newest file. *) + let files = List.map ( + fun file -> + let file = ssh_dir // file in + let stat = stat file in + (file, stat.st_mtime) + ) files in + let files = List.sort (fun (_,m1) (_,m2) -> compare m2 m1) files in + + fst (List.hd files) + +let read_key file + (* Read and return the public key. *) + let key = read_whole_file file in + if key = "" then + error (f_"ssh-inject: public key file (%s) is empty") file; + key + +let key_string_from_selector = function + | SystemKey -> + read_key (local_user_ssh_pubkey ()) + | KeyFile f -> + read_key f + | KeyString s -> + if String.length s < 1 then + error (f_"ssh-inject: key is an empty string"); + s + +(* Inject SSH key, where possible. *) +let do_ssh_inject_unix (g : Guestfs.guestfs) user selector + let key = key_string_from_selector selector in + assert (String.length key > 0); + + (* If the key doesn't have \n at the end, add it. *) + let len = String.length key in + let key = if key.[len-1] = '\n' then key else key ^ "\n" in + + (* Get user's home directory. *) + g#aug_init "/" 0; + let home_dir + try + let expr = sprintf "/files/etc/passwd/%s/home" user in + g#aug_get expr + with G.Error _ -> + error (f_"ssh-inject: the user %s does not exist on the guest") + user in + g#aug_close (); + + (* Create ~user/.ssh if it doesn't exist. *) + let ssh_dir = sprintf "%s/.ssh" home_dir in + if not (g#exists ssh_dir) then ( + g#mkdir ssh_dir; + g#chmod 0o755 ssh_dir + ); + + (* Create ~user/.ssh/authorized_keys if it doesn't exist. *) + let auth_keys = sprintf "%s/authorized_keys" ssh_dir in + if not (g#exists auth_keys) then ( + g#touch auth_keys; + g#chmod 0o644 auth_keys + ); + + (* Append the key. *) + g#write_append auth_keys key diff --git a/customize/ssh_key.mli b/customize/ssh_key.mli new file mode 100644 index 0000000..3223e55 --- /dev/null +++ b/customize/ssh_key.mli @@ -0,0 +1,31 @@ +(* virt-customize + * Copyright (C) 2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +type ssh_key_selector +| SystemKey (* Default key from the user in the system, in + * the style of ssh-copy-id(1)/default_ID_file. + *) +| KeyFile of string (* Key from the specified file. *) +| KeyString of string (* Key specified as string. *) + +val parse_selector : string -> ssh_key_selector +(** Parse the selector field in --ssh-ibject. Note this + doesn't parse the username part. Exits if the format is not valid. *) + +val do_ssh_inject_unix : Guestfs.guestfs -> string -> ssh_key_selector -> unit +(** ... *) diff --git a/generator/customize.ml b/generator/customize.ml index 8642a54..82ecb79 100644 --- a/generator/customize.ml +++ b/generator/customize.ml @@ -42,6 +42,7 @@ and op_type | TargetLinks of string (* target:link[:link...] *) | PasswordSelector of string (* password selector *) | UserPasswordSelector of string (* user:selector *) +| SSHKeySelector of string (* user:selector *) let ops = [ { op_name = "chmod"; @@ -260,6 +261,22 @@ It cannot delete directories, only regular files. =back"; }; + { op_name = "ssh-inject"; + op_type = SSHKeySelector "USER[:SELECTOR]"; + op_discrim = "`SSHInject"; + op_shortdesc = "Inject a public key into the guest"; + op_pod_longdesc = "\ +Inject an ssh key so the given C<USER> will be able to log in over +ssh without supplying a password. The C<USER> must exist already +in the guest. + +See L<virt-builder(1)/SSH KEYS> for the format of +the C<SELECTOR> field. + +You can have multiple I<--ssh-inject> options, for different users +and also for more keys for each user." + }; + { op_name = "timezone"; op_type = String "TIMEZONE"; op_discrim = "`Timezone"; @@ -539,6 +556,19 @@ let rec argspec () pr " s_\"%s\" ^ \" \" ^ s_\"%s\"\n" v shortdesc; pr " ),\n"; pr " Some %S, %S;\n" v longdesc + | { op_type = SSHKeySelector v; op_name = name; op_discrim = discrim; + op_shortdesc = shortdesc; op_pod_longdesc = longdesc } -> + pr " (\n"; + pr " \"--%s\",\n" name; + pr " Arg.String (\n"; + pr " fun s ->\n"; + pr " let user, selstr = string_split \":\" s in\n"; + pr " let sel = Ssh_key.parse_selector selstr in\n"; + pr " ops := %s (user, sel) :: !ops\n" discrim; + pr " ),\n"; + pr " s_\"%s\" ^ \" \" ^ s_\"%s\"\n" v shortdesc; + pr " ),\n"; + pr " Some %S, %S;\n" v longdesc ) ops; List.iter ( @@ -606,6 +636,10 @@ type ops = { op_name = name } -> pr " | %s of string * Password.password_selector\n (* --%s %s *)\n" discrim name v + | { op_type = SSHKeySelector v; op_discrim = discrim; + op_name = name } -> + pr " | %s of string * Ssh_key.ssh_key_selector\n (* --%s %s *)\n" + discrim name v ) ops; pr "]\n"; @@ -631,7 +665,7 @@ let generate_customize_synopsis_pod () | { op_type = Unit; op_name = n } -> n, sprintf "[--%s]" n | { op_type = String v | StringPair v | StringList v | TargetLinks v - | PasswordSelector v | UserPasswordSelector v; + | PasswordSelector v | UserPasswordSelector v | SSHKeySelector v; op_name = n } -> n, sprintf "[--%s %s]" n v ) ops @ @@ -671,7 +705,7 @@ let generate_customize_options_pod () | { op_type = Unit; op_name = n; op_pod_longdesc = ld } -> n, sprintf "B<--%s>" n, ld | { op_type = String v | StringPair v | StringList v | TargetLinks v - | PasswordSelector v | UserPasswordSelector v; + | PasswordSelector v | UserPasswordSelector v | SSHKeySelector v; op_name = n; op_pod_longdesc = ld } -> n, sprintf "B<--%s> %s" n v, ld ) ops @ diff --git a/po/POTFILES-ml b/po/POTFILES-ml index a3086eb..b6d88b0 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -25,6 +25,7 @@ customize/hostname.ml customize/password.ml customize/perl_edit.ml customize/random_seed.ml +customize/ssh_key.ml customize/timezone.ml customize/urandom.ml mllib/JSON.ml diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 6553c9c..17fe612 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -102,6 +102,7 @@ deps = \ $(top_builddir)/customize/firstboot.cmx \ $(top_builddir)/customize/perl_edit-c.o \ $(top_builddir)/customize/perl_edit.cmx \ + $(top_builddir)/customize/ssh_key.cmx \ $(top_builddir)/customize/customize_cmdline.cmx \ $(top_builddir)/customize/customize_run.cmx \ $(top_builddir)/fish/guestfish-uri.o \ diff --git a/v2v/Makefile.am b/v2v/Makefile.am index b4bb9cc..9217777 100644 --- a/v2v/Makefile.am +++ b/v2v/Makefile.am @@ -139,6 +139,7 @@ BOBJECTS = \ $(top_builddir)/customize/perl_edit.cmo \ $(top_builddir)/customize/crypt.cmo \ $(top_builddir)/customize/password.cmo \ + $(top_builddir)/customize/ssh_key.cmo \ $(top_builddir)/customize/customize_run.cmo \ $(SOURCES_ML:.ml=.cmo) XOBJECTS = $(BOBJECTS:.cmo=.cmx) -- 1.9.3
Pino Toscano
2014-Nov-03 18:42 UTC
Re: [Libguestfs] [PATCH] customize: Add --ssh-inject option for injecting SSH keys.
On Monday 03 November 2014 19:36:21 Pino Toscano wrote:> +val do_ssh_inject_unix : Guestfs.guestfs -> string -> ssh_key_selector -> unit > +(** ... *)Err... this is supposed to be: (** Inject on a generic Unix system (Linux, FreeBSD, etc) the ssh key for the specified user. *) (already fixed locally.) -- Pino Toscano
Apparently Analagous Threads
- [PATCH] customize: Add --ssh-inject option for injecting SSH keys.
- [PATCH] customize: add --commands-from-file
- [PATCH v2 0/2] basic subscription-manager support in virt-customize
- [PATCH] customize: Create .ssh as 0700 and .ssh/authorized_keys as 0600 (RHBZ#1260778).
- [PATCH 1/2] customize: minor function factoring in ssh_key