github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/cmd/fabric-ca-client/identity.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/cloudflare/cfssl/log"
    23  	"github.com/hyperledger/fabric-ca/api"
    24  	"github.com/hyperledger/fabric-ca/lib"
    25  	"github.com/hyperledger/fabric-ca/util"
    26  	"github.com/pkg/errors"
    27  	"github.com/spf13/cobra"
    28  )
    29  
    30  type identityArgs struct {
    31  	id     string
    32  	json   string
    33  	add    api.AddIdentityRequest
    34  	modify api.ModifyIdentityRequest
    35  	remove api.RemoveIdentityRequest
    36  }
    37  
    38  func (c *ClientCmd) newIdentityCommand() *cobra.Command {
    39  	identityCmd := &cobra.Command{
    40  		Use:   "identity",
    41  		Short: "Manage identities",
    42  		Long:  "Manage identities",
    43  	}
    44  	identityCmd.AddCommand(c.newListIdentityCommand())
    45  	identityCmd.AddCommand(c.newAddIdentityCommand())
    46  	identityCmd.AddCommand(c.newModifyIdentityCommand())
    47  	identityCmd.AddCommand(c.newRemoveIdentityCommand())
    48  	return identityCmd
    49  }
    50  
    51  func (c *ClientCmd) newListIdentityCommand() *cobra.Command {
    52  	identityListCmd := &cobra.Command{
    53  		Use:   "list",
    54  		Short: "List identities",
    55  		Long:  "List identities visible to caller",
    56  		PreRunE: func(cmd *cobra.Command, args []string) error {
    57  			log.Level = log.LevelWarning
    58  			err := c.configInit()
    59  			if err != nil {
    60  				return err
    61  			}
    62  
    63  			log.Debugf("Client configuration settings: %+v", c.clientCfg)
    64  
    65  			return nil
    66  		},
    67  		RunE: c.runListIdentity,
    68  	}
    69  	flags := identityListCmd.Flags()
    70  	flags.StringVarP(
    71  		&c.dynamicIdentity.id, "id", "", "", "Get identity information from the fabric-ca server")
    72  	return identityListCmd
    73  }
    74  
    75  func (c *ClientCmd) newAddIdentityCommand() *cobra.Command {
    76  	identityAddCmd := &cobra.Command{
    77  		Use:     "add <id>",
    78  		Short:   "Add identity",
    79  		Long:    "Add an identity",
    80  		Example: "fabric-ca-client identity add user1 --type peer",
    81  		PreRunE: c.identityPreRunE,
    82  		RunE:    c.runAddIdentity,
    83  	}
    84  	flags := identityAddCmd.Flags()
    85  	util.RegisterFlags(c.myViper, flags, &c.dynamicIdentity.add, nil)
    86  	flags.StringSliceVarP(
    87  		&c.cfgAttrs, "attrs", "", nil, "A list of comma-separated attributes of the form <name>=<value> (e.g. foo=foo1,bar=bar1)")
    88  	flags.StringVarP(
    89  		&c.dynamicIdentity.json, "json", "", "", "JSON string for adding a new identity")
    90  	return identityAddCmd
    91  }
    92  
    93  func (c *ClientCmd) newModifyIdentityCommand() *cobra.Command {
    94  	identityModifyCmd := &cobra.Command{
    95  		Use:     "modify <id>",
    96  		Short:   "Modify identity",
    97  		Long:    "Modify an existing identity",
    98  		Example: "fabric-ca-client identity modify user1 --type peer",
    99  		PreRunE: c.identityPreRunE,
   100  		RunE:    c.runModifyIdentity,
   101  	}
   102  	flags := identityModifyCmd.Flags()
   103  	tags := map[string]string{
   104  		"skip.id": "true",
   105  	}
   106  	util.RegisterFlags(c.myViper, flags, &c.dynamicIdentity.modify, tags)
   107  	flags.StringSliceVarP(
   108  		&c.cfgAttrs, "attrs", "", nil, "A list of comma-separated attributes of the form <name>=<value> (e.g. foo=foo1,bar=bar1)")
   109  	flags.StringVarP(
   110  		&c.dynamicIdentity.json, "json", "", "", "JSON string for modifying an existing identity")
   111  	return identityModifyCmd
   112  }
   113  
   114  func (c *ClientCmd) newRemoveIdentityCommand() *cobra.Command {
   115  	identityRemoveCmd := &cobra.Command{
   116  		Use:     "remove <id>",
   117  		Short:   "Remove identity",
   118  		Long:    "Remove an identity",
   119  		Example: "fabric-ca-client identity remove user1",
   120  		PreRunE: c.identityPreRunE,
   121  		RunE:    c.runRemoveIdentity,
   122  	}
   123  	flags := identityRemoveCmd.Flags()
   124  	flags.BoolVarP(
   125  		&c.dynamicIdentity.remove.Force, "force", "", false, "Forces removing your own identity")
   126  	return identityRemoveCmd
   127  }
   128  
   129  // The client side logic for executing list identity command
   130  func (c *ClientCmd) runListIdentity(cmd *cobra.Command, args []string) error {
   131  	log.Debug("Entered runListIdentity")
   132  
   133  	id, err := c.loadMyIdentity()
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	if c.dynamicIdentity.id != "" {
   139  		resp, err := id.GetIdentity(c.dynamicIdentity.id, c.clientCfg.CAName)
   140  		if err != nil {
   141  			return err
   142  		}
   143  
   144  		fmt.Printf("Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Attributes: %+v\n", resp.ID, resp.Type, resp.Affiliation, resp.MaxEnrollments, resp.Attributes)
   145  		return nil
   146  	}
   147  
   148  	err = id.GetAllIdentities(c.clientCfg.CAName, lib.IdentityDecoder)
   149  	if err != nil {
   150  		return err
   151  	}
   152  
   153  	return nil
   154  }
   155  
   156  // The client side logic for adding an identity
   157  func (c *ClientCmd) runAddIdentity(cmd *cobra.Command, args []string) error {
   158  	log.Debugf("Entered runAddIdentity: %+v", c.dynamicIdentity)
   159  	if c.dynamicIdentity.json != "" && checkOtherFlags(cmd) {
   160  		return errors.Errorf("Can't use 'json' flag in conjunction with other flags")
   161  	}
   162  
   163  	id, err := c.loadMyIdentity()
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	req := &api.AddIdentityRequest{}
   169  
   170  	if c.dynamicIdentity.json != "" {
   171  		err := util.Unmarshal([]byte(c.dynamicIdentity.json), &req, "addIdentity")
   172  		if err != nil {
   173  			return errors.Wrap(err, "Invalid value for --json option")
   174  		}
   175  	} else {
   176  		req = &c.dynamicIdentity.add
   177  		req.Attributes = c.clientCfg.ID.Attributes
   178  	}
   179  
   180  	req.ID = args[0]
   181  	req.CAName = c.clientCfg.CAName
   182  	resp, err := id.AddIdentity(req)
   183  	if err != nil {
   184  		return err
   185  	}
   186  
   187  	fmt.Printf("Successfully added identity - Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Secret: %s, Attributes: %+v\n", resp.ID, resp.Type, resp.Affiliation, resp.MaxEnrollments, resp.Secret, resp.Attributes)
   188  	return nil
   189  }
   190  
   191  // The client side logic for modifying an identity
   192  func (c *ClientCmd) runModifyIdentity(cmd *cobra.Command, args []string) error {
   193  	log.Debugf("Entered runModifyIdentity: %+v", c.dynamicIdentity)
   194  	if c.dynamicIdentity.json != "" && checkOtherFlags(cmd) {
   195  		return errors.Errorf("Can't use 'json' flag in conjunction with other flags")
   196  	}
   197  
   198  	req := &api.ModifyIdentityRequest{}
   199  
   200  	id, err := c.loadMyIdentity()
   201  	if err != nil {
   202  		return err
   203  	}
   204  
   205  	if c.dynamicIdentity.json != "" {
   206  		err := util.Unmarshal([]byte(c.dynamicIdentity.json), req, "modifyIdentity")
   207  		if err != nil {
   208  			return errors.Wrap(err, "Invalid value for --json option")
   209  		}
   210  	} else {
   211  		req = &c.dynamicIdentity.modify
   212  		req.Attributes = c.clientCfg.ID.Attributes
   213  	}
   214  
   215  	req.ID = args[0]
   216  	req.CAName = c.clientCfg.CAName
   217  	resp, err := id.ModifyIdentity(req)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	fmt.Printf("Successfully modified identity - Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Secret: %s, Attributes: %+v\n", resp.ID, resp.Type, resp.Affiliation, resp.MaxEnrollments, resp.Secret, resp.Attributes)
   223  	return nil
   224  }
   225  
   226  // The client side logic for removing an identity
   227  func (c *ClientCmd) runRemoveIdentity(cmd *cobra.Command, args []string) error {
   228  	log.Debugf("Entered runRemoveIdentity: %+v", c.dynamicIdentity)
   229  
   230  	id, err := c.loadMyIdentity()
   231  	if err != nil {
   232  		return err
   233  	}
   234  
   235  	req := &c.dynamicIdentity.remove
   236  	req.ID = args[0]
   237  	req.CAName = c.clientCfg.CAName
   238  	resp, err := id.RemoveIdentity(req)
   239  	if err != nil {
   240  		return err
   241  	}
   242  
   243  	fmt.Printf("Successfully removed identity - Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Attributes: %+v\n", resp.ID, resp.Type, resp.Affiliation, resp.MaxEnrollments, resp.Attributes)
   244  	return nil
   245  }
   246  
   247  func (c *ClientCmd) identityPreRunE(cmd *cobra.Command, args []string) error {
   248  	err := argsCheck(args, "Identity")
   249  	if err != nil {
   250  		return err
   251  	}
   252  
   253  	err = c.configInit()
   254  	if err != nil {
   255  		return err
   256  	}
   257  
   258  	log.Debugf("Client configuration settings: %+v", c.clientCfg)
   259  
   260  	return nil
   261  }
   262  
   263  // checkOtherFlags returns true if other flags besides '--json' are set
   264  // Viper.IsSet does not work correctly if there are defaults defined for
   265  // flags. This is a workaround until this bug is addressed in Viper.
   266  // Viper Bug: https://github.com/spf13/viper/issues/276
   267  func checkOtherFlags(cmd *cobra.Command) bool {
   268  	checkFlags := []string{"id", "type", "affiliation", "secret", "maxenrollments", "attrs"}
   269  	flags := cmd.Flags()
   270  	for _, checkFlag := range checkFlags {
   271  		flag := flags.Lookup(checkFlag)
   272  		if flag != nil {
   273  			if flag.Changed {
   274  				return true
   275  			}
   276  		}
   277  	}
   278  
   279  	return false
   280  }
   281  
   282  func argsCheck(args []string, field string) error {
   283  	if len(args) == 0 {
   284  		return errors.Errorf("%s name is required", field)
   285  	}
   286  	if len(args) > 1 {
   287  		return errors.Errorf("Unknown argument '%s', only the identity name should be passed in as non-flag argument", args[1])
   288  	}
   289  	return nil
   290  }