func (s *AuthKeysSuite) TestReadAuthorizedKeysErrors(c *gc.C) { ctx := testing.Context(c) _, err := common.ReadAuthorizedKeys(ctx, "") c.Assert(err, gc.ErrorMatches, "no public ssh keys found") c.Assert(err, gc.Equals, common.ErrNoAuthorizedKeys) _, err = common.ReadAuthorizedKeys(ctx, filepath.Join(s.dotssh, "notthere.pub")) c.Assert(err, gc.ErrorMatches, "no public ssh keys found") c.Assert(err, gc.Equals, common.ErrNoAuthorizedKeys) }
func (s *AuthKeysSuite) TestReadAuthorizedKeys(c *gc.C) { ctx := testing.Context(c) writeFile(c, filepath.Join(s.dotssh, "id_rsa.pub"), "id_rsa") writeFile(c, filepath.Join(s.dotssh, "identity.pub"), "identity") writeFile(c, filepath.Join(s.dotssh, "test.pub"), "test") keys, err := common.ReadAuthorizedKeys(ctx, "") c.Assert(err, jc.ErrorIsNil) c.Assert(keys, gc.Equals, "id_rsa\nidentity\n") keys, err = common.ReadAuthorizedKeys(ctx, "test.pub") // relative to ~/.ssh c.Assert(err, jc.ErrorIsNil) c.Assert(keys, gc.Equals, "test\n") }
func (s *AuthKeysSuite) TestReadAuthorizedKeysClientKeys(c *gc.C) { ctx := testing.Context(c) keydir := filepath.Join(s.dotssh, "juju") err := ssh.LoadClientKeys(keydir) // auto-generates a key pair c.Assert(err, jc.ErrorIsNil) pubkeyFiles := ssh.PublicKeyFiles() c.Assert(pubkeyFiles, gc.HasLen, 1) data, err := ioutil.ReadFile(pubkeyFiles[0]) c.Assert(err, jc.ErrorIsNil) prefix := strings.Trim(string(data), "\n") + "\n" writeFile(c, filepath.Join(s.dotssh, "id_rsa.pub"), "id_rsa") writeFile(c, filepath.Join(s.dotssh, "test.pub"), "test") keys, err := common.ReadAuthorizedKeys(ctx, "") c.Assert(err, jc.ErrorIsNil) c.Assert(keys, gc.Equals, prefix+"id_rsa\n") keys, err = common.ReadAuthorizedKeys(ctx, "test.pub") c.Assert(err, jc.ErrorIsNil) c.Assert(keys, gc.Equals, prefix+"test\n") keys, err = common.ReadAuthorizedKeys(ctx, "notthere.pub") c.Assert(err, jc.ErrorIsNil) c.Assert(keys, gc.Equals, prefix) }
func (c *addCommand) Run(ctx *cmd.Context) error { var err error c.Constraints, err = common.ParseConstraints(ctx, c.ConstraintsStr) if err != nil { return err } client, err := c.getClientAPI() if err != nil { return errors.Trace(err) } defer client.Close() var machineManager MachineManagerAPI if len(c.Disks) > 0 { machineManager, err = c.getMachineManagerAPI() if err != nil { return errors.Trace(err) } defer machineManager.Close() if machineManager.BestAPIVersion() < 1 { return errors.New("cannot add machines with disks: not supported by the API server") } } logger.Infof("load config") modelConfigClient, err := c.getModelConfigAPI() if err != nil { return errors.Trace(err) } defer modelConfigClient.Close() configAttrs, err := modelConfigClient.ModelGet() if err != nil { if params.IsCodeUnauthorized(err) { common.PermissionsMessage(ctx.Stderr, "add a machine to this model") } return errors.Trace(err) } config, err := config.New(config.NoDefaults, configAttrs) if err != nil { return errors.Trace(err) } if c.Placement != nil && c.Placement.Scope == "ssh" { logger.Infof("manual provisioning") authKeys, err := common.ReadAuthorizedKeys(ctx, "") if err != nil { return errors.Annotate(err, "reading authorized-keys") } args := manual.ProvisionMachineArgs{ Host: c.Placement.Directive, Client: client, Stdin: ctx.Stdin, Stdout: ctx.Stdout, Stderr: ctx.Stderr, AuthorizedKeys: authKeys, UpdateBehavior: ¶ms.UpdateBehavior{ config.EnableOSRefreshUpdate(), config.EnableOSUpgrade(), }, } machineId, err := manualProvisioner(args) if err == nil { ctx.Infof("created machine %v", machineId) } return err } logger.Infof("model provisioning") if c.Placement != nil && c.Placement.Scope == "model-uuid" { uuid, ok := client.ModelUUID() if !ok { return errors.New("API connection is controller-only (should never happen)") } c.Placement.Scope = uuid } if c.Placement != nil && c.Placement.Scope == instance.MachineScope { // It does not make sense to add-machine <id>. return errors.Errorf("machine-id cannot be specified when adding machines") } jobs := []multiwatcher.MachineJob{multiwatcher.JobHostUnits} machineParams := params.AddMachineParams{ Placement: c.Placement, Series: c.Series, Constraints: c.Constraints, Jobs: jobs, Disks: c.Disks, } machines := make([]params.AddMachineParams, c.NumMachines) for i := 0; i < c.NumMachines; i++ { machines[i] = machineParams } var results []params.AddMachinesResult // If storage is specified, we attempt to use a new API on the service facade. if len(c.Disks) > 0 { results, err = machineManager.AddMachines(machines) } else { results, err = client.AddMachines(machines) } if params.IsCodeOperationBlocked(err) { return block.ProcessBlockedError(err, block.BlockChange) } if err != nil { return errors.Trace(err) } errs := []error{} for _, machineInfo := range results { if machineInfo.Error != nil { errs = append(errs, machineInfo.Error) continue } machineId := machineInfo.Machine if names.IsContainerMachine(machineId) { ctx.Infof("created container %v", machineId) } else { ctx.Infof("created machine %v", machineId) } } if len(errs) == 1 { fmt.Fprint(ctx.Stderr, "failed to create 1 machine\n") return errs[0] } if len(errs) > 1 { fmt.Fprintf(ctx.Stderr, "failed to create %d machines\n", len(errs)) returnErr := []string{} for _, e := range errs { returnErr = append(returnErr, e.Error()) } return errors.New(strings.Join(returnErr, ", ")) } return nil }