Commit 3d7ba7f7 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

feat: update revocation commands of irma cli

parent e1e60e99
......@@ -46,7 +46,7 @@ var requestCmd = &cobra.Command{
},
}
func signRequest(request irma.RequestorRequest, name, authmethod, key string) (string, error) {
func configureJWTKey(authmethod, key string) (interface{}, jwt.SigningMethod, error) {
var (
err error
sk interface{}
......@@ -61,17 +61,25 @@ func signRequest(request irma.RequestorRequest, name, authmethod, key string) (s
case "hmac":
jwtalg = jwt.SigningMethodHS256
if sk, err = fs.Base64Decode(bts); err != nil {
return "", err
return nil, nil, err
}
case "rsa":
jwtalg = jwt.SigningMethodRS256
if sk, err = jwt.ParseRSAPrivateKeyFromPEM(bts); err != nil {
return "", err
return nil, nil, err
}
default:
return "", errors.Errorf("Unsupported signing algorithm: '%s'", authmethod)
return nil, nil, errors.Errorf("Unsupported signing algorithm: '%s'", authmethod)
}
return sk, jwtalg, nil
}
func signRequest(request irma.RequestorRequest, name, authmethod, key string) (string, error) {
sk, jwtalg, err := configureJWTKey(authmethod, key)
if err != nil {
return "", err
}
return irma.SignRequestorRequest(request, jwtalg, sk, name)
}
......
package cmd
import (
"path/filepath"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/revocation"
irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/spf13/cobra"
)
var revokeEnableCmd = &cobra.Command{
Use: "enable CREDENTIALTYPE [PATH]",
Use: "enable CREDENTIALTYPE",
Short: "Enable revocation for a credential type",
Long: `Enable revocation for a given credential type.
Must be done (and can only be done) by the issuer of the specified credential type, if enable in the
scheme. The revocation database is written to or updated from PATH, or the default IRMA storage path
(` + irma.DefaultDataPath() + `).`,
Args: cobra.RangeArgs(1, 2),
scheme.`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
path := irma.DefaultDataPath()
if len(args) > 1 {
path = args[1]
flags := cmd.Flags()
schemespath, _ := flags.GetString("schemes-path")
authmethod, _ := flags.GetString("auth-method")
key, _ := flags.GetString("key")
name, _ := flags.GetString("name")
verbosity, _ := cmd.Flags().GetCount("verbose")
request := &irma.RevocationRequest{
LDContext: irma.LDContextRevocationRequest,
CredentialType: irma.NewCredentialTypeIdentifier(args[0]),
Enable: true,
}
db, nonrevKey := configureRevocation(cmd, path, args[0])
if err := db.EnableRevocation(nonrevKey); err != nil {
die("failed to enable revocation", err)
}
postRevocation(request, schemespath, authmethod, key, name, verbosity)
},
}
func configureRevocation(cmd *cobra.Command, path, credtype string) (*revocation.DB, *revocation.PrivateKey) {
var err error
if err = fs.EnsureDirectoryExists(filepath.Join(path, "revocation")); err != nil {
die("failed to create revocation database folder", err)
}
// parse irma_configuration and lookup credential type
irmaconf, err := irma.NewConfiguration(filepath.Join(path, "irma_configuration"), irma.ConfigurationOptions{})
if err != nil {
die("failed to open irma_configuration", err)
}
if err = irmaconf.ParseFolder(); err != nil {
die("failed to parse irma_configuration", err)
}
id := irma.NewCredentialTypeIdentifier(credtype)
typ := irmaconf.CredentialTypes[id]
if typ == nil {
die("unknown credential type", nil)
}
// Read private key from either flag or irma_configuration
var privatekey *gabi.PrivateKey
privkeypath, _ := cmd.Flags().GetString("privatekey")
if privkeypath != "" {
privatekey, err = gabi.NewPrivateKeyFromFile(privkeypath)
} else {
privatekey, err = irmaconf.PrivateKey(typ.IssuerIdentifier())
}
if err != nil {
die("failed to read private key", err)
}
if privatekey == nil {
die("no private key specified and none found in irma_configuration", nil)
}
nonrevKey, err := privatekey.RevocationKey()
if err != nil {
die("failed to load nonrevocation private key from IRMA private key", err)
}
db, err := irmaconf.RevocationDB(id)
if err != nil {
die("failed to load revocation database", err)
}
return db, nonrevKey
}
func init() {
revokeEnableCmd.Flags().StringP("privatekey", "s", "", `Issuer private key for specified credential type`)
flags := revokeEnableCmd.Flags()
flags.StringP("schemes-path", "s", irma.DefaultSchemesPath(), "path to irma_configuration")
flags.StringP("auth-method", "a", "none", "Authentication method to server (none, token, rsa, hmac)")
flags.String("key", "", "Key to sign request with")
flags.String("name", "", "Requestor name")
flags.CountP("verbose", "v", "verbose (repeatable)")
revocationCmd.AddCommand(revokeEnableCmd)
}
package cmd
import (
"time"
irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/server"
"github.com/spf13/cobra"
)
var revokeCmd = &cobra.Command{
Use: "revoke CREDENTIALTYPE KEY",
Short: "Revoke a previously issued credential identified by a given key",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
flags := cmd.Flags()
schemespath, _ := flags.GetString("schemes-path")
authmethod, _ := flags.GetString("auth-method")
key, _ := flags.GetString("key")
name, _ := flags.GetString("name")
verbosity, _ := cmd.Flags().GetCount("verbose")
request := &irma.RevocationRequest{
LDContext: irma.LDContextRevocationRequest,
CredentialType: irma.NewCredentialTypeIdentifier(args[0]),
Key: args[1],
}
postRevocation(request, schemespath, authmethod, key, name, verbosity)
},
}
func postRevocation(request *irma.RevocationRequest, schemespath, authmethod, key, name string, verbosity int) {
logger.Level = server.Verbosity(verbosity)
irma.Logger = logger
conf, err := irma.NewConfiguration(schemespath, irma.ConfigurationOptions{ReadOnly: true})
if err != nil {
die("failed to open irma_configuration", err)
}
if err = conf.ParseFolder(); err != nil {
die("failed to parse irma_configuration", err)
}
credtype, known := conf.CredentialTypes[request.CredentialType]
if !known {
die("unknown credential type", nil)
}
if credtype.RevocationServer == "" {
die("credential type does not support revocation", nil)
}
transport := irma.NewHTTPTransport(credtype.RevocationServer)
switch authmethod {
case "none":
err = transport.Post("session", nil, request)
case "token":
transport.SetHeader("Authorization", key)
err = transport.Post("session", nil, request)
case "hmac", "rsa":
sk, jwtalg, err := configureJWTKey(authmethod, key)
j := irma.RevocationJwt{
ServerJwt: irma.ServerJwt{
ServerName: name,
IssuedAt: irma.Timestamp(time.Now()),
},
Request: request,
}
jwtstr, err := j.Sign(jwtalg, sk)
if err != nil {
die("failed to sign JWT", err)
}
err = transport.Post("session", nil, jwtstr)
default:
die("Invalid authentication method (must be none, token, hmac or rsa)", nil)
}
if err != nil {
die("failed to post revocation request", err)
}
}
func init() {
flags := revokeCmd.Flags()
flags.StringP("schemes-path", "s", irma.DefaultSchemesPath(), "path to irma_configuration")
flags.StringP("auth-method", "a", "none", "Authentication method to server (none, token, rsa, hmac)")
flags.String("key", "", "Key to sign request with")
flags.String("name", "", "Requestor name")
flags.CountP("verbose", "v", "verbose (repeatable)")
revocationCmd.AddCommand(revokeCmd)
}
package cmd
import (
irma "github.com/privacybydesign/irmago"
"github.com/spf13/cobra"
)
var revokeCmd = &cobra.Command{
Use: "revoke CREDENTIALTYPE KEY [PATH]",
Short: "Revoke a previously issued credential identified by a given key",
Args: cobra.RangeArgs(2, 3),
Run: func(cmd *cobra.Command, args []string) {
irmaconf := irma.DefaultSchemesPath()
if len(args) == 3 {
irmaconf = args[2]
} else if irmaconf == "" {
die("Failed to find default irma_configuration path", nil)
}
conf, err := irma.NewConfigurationReadOnly(irmaconf)
if err != nil {
die("", err)
}
if err = conf.ParseFolder(); err != nil {
die("", err)
}
cred := irma.NewCredentialTypeIdentifier(args[0])
if _, known := conf.CredentialTypes[cred]; !known {
die("unknown credential type", nil)
}
flags := cmd.Flags()
authmethod, _ := flags.GetString("authmethod")
key, _ := flags.GetString("key")
name, _ := flags.GetString("name")
_ = &irma.RevocationRequest{
LDContext: irma.LDContextRevocationRequest,
CredentialType: cred,
Key: args[1],
}
},
}
func init() {
flags := revocationCmd.Flags()
flags.StringP("authmethod", "a", "none", "Authentication method to server (none, token, rsa, hmac)")
flags.String("key", "", "Key to sign request with")
flags.String("name", "", "Requestor name")
revocationCmd.AddCommand(revokeCmd)
}
......@@ -42,13 +42,16 @@ func init() {
func die(message string, err error) {
var m string
if message != "" {
m = message + ": "
m = message
}
if err != nil {
if message != "" {
m += ": "
}
if e, ok := err.(*errors.Error); ok && logger.IsLevelEnabled(logrus.DebugLevel) {
m += e.ErrorStack()
} else {
m = m + err.Error()
m += err.Error()
}
}
......
......@@ -199,7 +199,8 @@ type AttributeRequest struct {
type RevocationRequest struct {
LDContext string `json:"@context,omitempty"`
CredentialType CredentialTypeIdentifier `json:"type"`
Key string `json:"key"`
Key string `json:"key,omitempty"`
Enable bool `json:"enable,omitempty"`
}
func (r *RevocationRequest) Validate() error {
......@@ -923,6 +924,10 @@ func (claims *RevocationJwt) Valid() error {
return nil
}
func (claims *RevocationJwt) Sign(method jwt.SigningMethod, key interface{}) (string, error) {
return jwt.NewWithClaims(method, claims).SignedString(key)
}
func (claims *ServiceProviderJwt) Action() Action { return ActionDisclosing }
func (claims *SignatureRequestorJwt) Action() Action { return ActionSigning }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment