-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
External policy hook #252
Merged
Merged
External policy hook #252
Changes from 13 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
a2af96b
external policy hook
e-asphyx 827414c
add client key hash to the hook metadata
e-asphyx 0ad3be0
oops
e-asphyx 923b583
Merge branch 'main' into external-policy-hook
e-asphyx 2450a00
more tests
e-asphyx c932c2e
whitelist service
e-asphyx a78f3a1
it fix
e-asphyx ea92c5a
service renamed
e-asphyx ae99b78
Merge branch 'main' into external-policy-hook
e-asphyx 64d1474
Updated documentation
e-asphyx 807eebb
mod tidy
e-asphyx d5549d9
Update remote_policy.md
e-asphyx 6340f71
Update remote_policy.md
e-asphyx 348c562
Revert changes to root .gitignore file
danielelisi b85be7c
Merge branch 'main' into external-policy-hook
danielelisi ce5a728
Remove redundant README.md file in docs folder
danielelisi ea3f2fb
Add Remote policy service documentation to the website sidebar
danielelisi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,5 +21,3 @@ vendor/ | |
dist | ||
.release-env | ||
.docker-creds | ||
signatory | ||
signatory-cli | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
approve-list-svc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Approve List Service | ||
|
||
The reference implementation of an external policy service. | ||
|
||
For configuration see [an example](config_example.yaml) | ||
|
||
## Start | ||
|
||
``` | ||
approve-list-svc -c config serve | ||
``` | ||
|
||
## Print the public key | ||
|
||
``` | ||
approve-list-svc -c config pub | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/ecadlabs/signatory/cmd/approve-list-svc/server" | ||
"github.com/ecadlabs/signatory/pkg/tezos" | ||
log "github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var rootCmd = &cobra.Command{ | ||
Use: "approve-list-svc", | ||
Short: "Example IP approve list external policy service", | ||
} | ||
|
||
var confFile string | ||
|
||
var pubCmd = &cobra.Command{ | ||
Use: "pub", | ||
Short: "Print the authentication public key", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
conf, err := ReadConfig(confFile) | ||
if err != nil { | ||
return err | ||
} | ||
pk, err := conf.GetPrivateKey() | ||
if err != nil { | ||
return err | ||
} | ||
if pk == nil { | ||
return errors.New("private key is not specified") | ||
} | ||
|
||
pub, err := tezos.EncodePublicKey(pk.Public()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Printf("Public key: %s\n", pub) | ||
return nil | ||
}, | ||
} | ||
|
||
var serveCmd = &cobra.Command{ | ||
Use: "serve", | ||
Short: "Start the server", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
conf, err := ReadConfig(confFile) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pk, err := conf.GetPrivateKey() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ips, nets, err := conf.Addresses() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
srv := server.Server{ | ||
Address: conf.Address, | ||
PrivateKey: pk, | ||
Addresses: ips, | ||
Nets: nets, | ||
} | ||
|
||
s := srv.New() | ||
log.Printf("HTTP server is listening for connections on %s", srv.Address) | ||
log.Println(s.ListenAndServe()) | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
rootCmd.PersistentFlags().StringVarP(&confFile, "config", "c", "", "Config file") | ||
rootCmd.AddCommand(pubCmd) | ||
rootCmd.AddCommand(serveCmd) | ||
} | ||
|
||
func main() { | ||
if err := rootCmd.Execute(); err != nil { | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/x509" | ||
"encoding/pem" | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"net" | ||
|
||
"github.com/ecadlabs/signatory/pkg/cryptoutils" | ||
"github.com/ecadlabs/signatory/pkg/tezos" | ||
yaml "gopkg.in/yaml.v3" | ||
) | ||
|
||
type Config struct { | ||
Address string `yaml:"address"` | ||
PrivateKey string `yaml:"private_key"` | ||
PrivateKeyFile string `yaml:"private_key_file"` | ||
List []string `yaml:"list"` | ||
} | ||
|
||
func (conf *Config) Addresses() ([]net.IP, []*net.IPNet, error) { | ||
var ( | ||
ips []net.IP | ||
nets []*net.IPNet | ||
) | ||
for _, addr := range conf.List { | ||
if _, n, err := net.ParseCIDR(addr); err == nil { | ||
nets = append(nets, n) | ||
} else { | ||
if ip := net.ParseIP(addr); ip != nil { | ||
ips = append(ips, ip) | ||
} else { | ||
return nil, nil, fmt.Errorf("invalid address: %s", addr) | ||
} | ||
} | ||
} | ||
return ips, nets, nil | ||
} | ||
|
||
func (conf *Config) GetPrivateKey() (cryptoutils.PrivateKey, error) { | ||
var keyData []byte | ||
if conf.PrivateKey != "" { | ||
if pk, err := tezos.ParsePrivateKey(conf.PrivateKey, nil); err == nil { | ||
return pk, nil | ||
} else { | ||
keyData = []byte(conf.PrivateKey) | ||
} | ||
} else { | ||
if conf.PrivateKeyFile == "" { | ||
return nil, nil | ||
} | ||
var err error | ||
if keyData, err = ioutil.ReadFile(conf.PrivateKeyFile); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
b, _ := pem.Decode(keyData) | ||
if b == nil { | ||
return nil, errors.New("can't parse private key PEM block") | ||
} | ||
|
||
key, err := x509.ParsePKCS8PrivateKey(b.Bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
pk, ok := key.(cryptoutils.PrivateKey) | ||
if !ok { | ||
return nil, errors.New("unexpected private key type") | ||
} | ||
return pk, nil | ||
} | ||
|
||
func ReadConfig(file string) (*Config, error) { | ||
yamlFile, err := ioutil.ReadFile(file) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var c Config | ||
if err = yaml.Unmarshal(yamlFile, &c); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &c, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# host:port to listen on | ||
address: :6733 | ||
|
||
# Optional private key for authenticated replies. Can be either Base58 encoded private key (see `signatory-tools gen-key`) | ||
# of PEM encoded PKCS8 key data | ||
private_key: edsk3YfMTdSzkFqLtmiZoFtEN6sR9jp64zin7f4jUTJiKbTLCqkkcJ | ||
|
||
# Alternatively PEM file can be stored separately | ||
#private_key_file: path_to_pem_file | ||
|
||
# List of allowed addresses which can be IPv4/IPv6 addresses or CIDR network addresses | ||
list: | ||
- 192.168.88.254 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package server | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net" | ||
"net/http" | ||
|
||
"github.com/ecadlabs/signatory/pkg/cryptoutils" | ||
"github.com/ecadlabs/signatory/pkg/signatory" | ||
"github.com/ecadlabs/signatory/pkg/tezos" | ||
"github.com/ecadlabs/signatory/pkg/tezos/utils" | ||
) | ||
|
||
type Server struct { | ||
Address string | ||
PrivateKey cryptoutils.PrivateKey | ||
Addresses []net.IP | ||
Nets []*net.IPNet | ||
} | ||
|
||
func (s *Server) Handler() (http.Handler, error) { | ||
pub := s.PrivateKey.Public() | ||
hash, err := tezos.EncodePublicKeyHash(pub) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
var req signatory.PolicyHookRequest | ||
dec := json.NewDecoder(r.Body) | ||
if err := dec.Decode(&req); err != nil { | ||
w.WriteHeader(http.StatusBadRequest) | ||
return | ||
} | ||
|
||
var ok bool | ||
for _, n := range s.Nets { | ||
if n.Contains(req.Source) { | ||
ok = true | ||
break | ||
} | ||
} | ||
if !ok { | ||
for _, a := range s.Addresses { | ||
if a.Equal(req.Source) { | ||
ok = true | ||
break | ||
} | ||
} | ||
} | ||
|
||
if s.PrivateKey != nil { | ||
var status int | ||
if ok { | ||
status = http.StatusOK | ||
} else { | ||
status = http.StatusForbidden | ||
} | ||
|
||
replyPl := signatory.PolicyHookReplyPayload{ | ||
Status: status, | ||
PublicKeyHash: hash, | ||
Nonce: req.Nonce, | ||
} | ||
|
||
if !ok { | ||
replyPl.Error = fmt.Sprintf("address %s is not allowed", req.Source) | ||
} | ||
|
||
buf, err := json.Marshal(&replyPl) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
digest := utils.DigestFunc(buf) | ||
sig, err := cryptoutils.Sign(s.PrivateKey, digest[:]) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
s, err := tezos.EncodeGenericSignature(sig) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
reply := signatory.PolicyHookReply{ | ||
Payload: buf, | ||
Signature: s, | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(status) | ||
json.NewEncoder(w).Encode(&reply) | ||
} else { | ||
var status int | ||
if ok { | ||
status = http.StatusNoContent | ||
} else { | ||
status = http.StatusForbidden | ||
} | ||
w.WriteHeader(status) | ||
} | ||
}), nil | ||
} | ||
|
||
func (s *Server) New() *http.Server { | ||
h, err := s.Handler() | ||
if err != nil { | ||
return nil | ||
} | ||
return &http.Server{ | ||
Handler: h, | ||
Addr: s.Address, | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you removing the compiled binaries from the
.gitignore
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll revert this change in the
.gitignore
since when we compile withmake all
the Signatory binaries are added to the root folder.