mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Cert CLI stuff, module bump.
This commit is contained in:
parent
782f15f8c9
commit
fe01352412
9 changed files with 162 additions and 19 deletions
|
@ -28,8 +28,6 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
|
|||
|
||||
switch args[0] {
|
||||
|
||||
case "list":
|
||||
|
||||
case "newsid":
|
||||
if len(args) > 2 {
|
||||
Help()
|
||||
|
@ -86,17 +84,18 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
|
|||
Help()
|
||||
return 1
|
||||
}
|
||||
var csr zerotier.Certificate
|
||||
|
||||
csrBytes, err := ioutil.ReadFile(args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: unable to read CSR from %s: %s\n", args[1], err.Error())
|
||||
return 1
|
||||
}
|
||||
c, err := zerotier.NewCertificateFromBytes(csrBytes, false)
|
||||
csr, err := zerotier.NewCertificateFromBytes(csrBytes, false)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: CSR in %s is invalid: %s\n", args[1], err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
id := readIdentity(args[2])
|
||||
if id == nil {
|
||||
fmt.Printf("ERROR: unable to read identity from %s\n", args[2])
|
||||
|
@ -106,12 +105,13 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
|
|||
fmt.Printf("ERROR: signing identity in %s lacks private key\n", args[2])
|
||||
return 1
|
||||
}
|
||||
c, err = csr.Sign(id)
|
||||
|
||||
cert, err := csr.Sign(id)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: error signing CSR or generating certificate: %s\n", err.Error())
|
||||
return 1
|
||||
}
|
||||
cb, err := c.Marshal()
|
||||
cb, err := cert.Marshal()
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: error marshaling signed certificate: %s\n", err.Error())
|
||||
return 1
|
||||
|
@ -124,7 +124,28 @@ func Cert(basePath string, authTokenGenerator func() string, args []string, json
|
|||
return 1
|
||||
}
|
||||
|
||||
case "verify":
|
||||
case "verify", "dump":
|
||||
if len(args) != 2 {
|
||||
Help()
|
||||
return 1
|
||||
}
|
||||
certBytes, err := ioutil.ReadFile(args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: unable to read certificate from %s: %s\n", args[1], err.Error())
|
||||
return 1
|
||||
}
|
||||
cert, err := zerotier.NewCertificateFromBytes(certBytes, true)
|
||||
if err != nil {
|
||||
fmt.Printf("FAILED: certificate in %s invalid: %s\n", args[1], err.Error())
|
||||
return 1
|
||||
}
|
||||
if args[0] == "dump" {
|
||||
fmt.Println(cert.JSON())
|
||||
} else {
|
||||
fmt.Println("OK")
|
||||
}
|
||||
|
||||
case "list":
|
||||
|
||||
case "show":
|
||||
if len(args) != 1 {
|
||||
|
|
|
@ -37,7 +37,7 @@ Common Operations:
|
|||
help Show this help
|
||||
version Print version
|
||||
|
||||
status Show node status and configuration
|
||||
· status Show node status and configuration
|
||||
|
||||
· set [option] [value] - Get or set node configuration
|
||||
port <port> Primary P2P port
|
||||
|
@ -95,11 +95,12 @@ Advanced Operations:
|
|||
|
||||
cert <command> [args] - Certificate management
|
||||
· list List certificates in local node store
|
||||
· show [serial] List or show details of a certificate
|
||||
· show <serial> List or show details of a certificate
|
||||
newsid <secret out> Create a new subject unique ID
|
||||
newcsr <subject> <secret> <csr out> Create a subject CSR
|
||||
sign <csr> <identity> <cert out> Sign a CSR to create a certificate
|
||||
· verify <cert> Verify a certificate
|
||||
verify <cert> Verify certificate (not entire chain)
|
||||
dump <cert> Verify and print certificate
|
||||
· import <cert> [trust,[trust]] Import certificate into this node
|
||||
rootca Certificate is a root CA (trust flag)
|
||||
ztrootset ZeroTier root node set (trust flag)
|
||||
|
|
|
@ -2411,7 +2411,7 @@ ZT_SDK_API int ZT_Node_tryPeer(
|
|||
* @param cert Certificate object, or set to NULL if certData and certSize are to be used
|
||||
* @param certData Certificate binary data if 'cert' is NULL, NULL otherwise
|
||||
* @param certSize Size of certificate binary data, 0 if none
|
||||
* @return
|
||||
* @return Certificate error or ZT_CERTIFICATE_ERROR_NONE on success
|
||||
*/
|
||||
ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
|
||||
ZT_Node *node,
|
||||
|
@ -2422,6 +2422,22 @@ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate(
|
|||
const void *certData,
|
||||
unsigned int certSize);
|
||||
|
||||
/**
|
||||
* Delete a certificate from this node's certificate store
|
||||
*
|
||||
* Note that deleting CA certificates may also imply deletion of certificates
|
||||
* that depend on them for full chain verification.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||
* @param serialNo 48-byte / 384-bit serial number of certificate to delete
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
const void *serialNo);
|
||||
|
||||
/**
|
||||
* List certificates installed in this node's trust store
|
||||
*
|
||||
|
|
2
go.mod
2
go.mod
|
@ -5,5 +5,5 @@ go 1.13
|
|||
require (
|
||||
github.com/Microsoft/go-winio v0.4.14
|
||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
|
||||
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d // indirect
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -13,5 +13,5 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d h1:QQrM/CCYEzTs91GZylDCQjGHudbPTxF/1fvXdVh5lMo=
|
||||
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
|
@ -16,6 +16,7 @@ package zerotier
|
|||
import (
|
||||
"bytes"
|
||||
secrand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -217,10 +218,12 @@ func apiCheckAuth(out http.ResponseWriter, req *http.Request, token string) bool
|
|||
if len(ah) > 0 && strings.TrimSpace(ah) == ("bearer "+token) {
|
||||
return true
|
||||
}
|
||||
|
||||
ah = req.Header.Get("X-ZT1-Auth")
|
||||
if len(ah) > 0 && strings.TrimSpace(ah) == token {
|
||||
return true
|
||||
}
|
||||
|
||||
_ = apiSendObj(out, req, http.StatusUnauthorized, &APIErr{"authorization token not found or incorrect (checked X-ZT1-Auth and Authorization headers)"})
|
||||
return false
|
||||
}
|
||||
|
@ -252,6 +255,8 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
|
||||
smux := http.NewServeMux()
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
smux.HandleFunc("/status", func(out http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
|
@ -298,6 +303,8 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
smux.HandleFunc("/config", func(out http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
|
@ -330,6 +337,8 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
smux.HandleFunc("/peer/", func(out http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
|
||||
|
@ -397,6 +406,8 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
smux.HandleFunc("/network/", func(out http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
|
@ -421,6 +432,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
|
||||
if req.Method == http.MethodDelete {
|
||||
|
||||
if queriedID == 0 {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"only specific networks can be deleted"})
|
||||
return
|
||||
|
@ -434,7 +446,9 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
}
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"network not found"})
|
||||
|
||||
} else if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
|
||||
if queriedID == 0 {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, nil)
|
||||
return
|
||||
|
@ -460,7 +474,9 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
_ = apiSendObj(out, req, http.StatusOK, apiNetworkFromNetwork(n))
|
||||
}
|
||||
}
|
||||
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
|
||||
networks := node.Networks()
|
||||
if queriedID == 0 { // no queried ID lists all networks
|
||||
nws := make([]*APINetwork, 0, len(networks))
|
||||
|
@ -477,12 +493,82 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
|||
}
|
||||
}
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"network not found"})
|
||||
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE")
|
||||
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"unsupported method " + req.Method})
|
||||
}
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
smux.HandleFunc("/cert/", func(out http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
_ = apiSendObj(out, req, http.StatusInternalServerError, nil)
|
||||
}
|
||||
}()
|
||||
|
||||
if !apiCheckAuth(out, req, authToken) {
|
||||
return
|
||||
}
|
||||
apiSetStandardHeaders(out)
|
||||
|
||||
var queriedSerialNo []byte
|
||||
if len(req.URL.Path) > 6 {
|
||||
b, err := base64.URLEncoding.DecodeString(req.URL.Path[6:])
|
||||
if err != nil || len(b) != CertificateSerialNoSize {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"invalid base64 serial number in certificate path"})
|
||||
return
|
||||
}
|
||||
queriedSerialNo = b
|
||||
}
|
||||
|
||||
if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
|
||||
certs, err := node.ListCertificates()
|
||||
if err != nil {
|
||||
_ = apiSendObj(out, req, http.StatusInternalServerError, &APIErr{"unexpected error listing certificates"})
|
||||
return
|
||||
}
|
||||
|
||||
if len(queriedSerialNo) == CertificateSerialNoSize {
|
||||
for _, c := range certs {
|
||||
if bytes.Equal(c.Certificate.SerialNo, queriedSerialNo) {
|
||||
_ = apiSendObj(out, req, http.StatusOK, c)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_ = apiSendObj(out, req, http.StatusOK, certs)
|
||||
}
|
||||
|
||||
} else if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
|
||||
var lc LocalCertificate
|
||||
if apiReadObj(out, req, &lc) == nil {
|
||||
if lc.Certificate == nil {
|
||||
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"missing certificate"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
} else if req.Method == http.MethodDelete {
|
||||
|
||||
if len(queriedSerialNo) == CertificateSerialNoSize {
|
||||
} else {
|
||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"certificate not found"})
|
||||
}
|
||||
|
||||
} else {
|
||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST, DELETE")
|
||||
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"unsupported method " + req.Method})
|
||||
}
|
||||
})
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
listener, err := createNamedSocketListener(basePath, APISocketName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -18,6 +18,7 @@ package zerotier
|
|||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
@ -96,6 +97,12 @@ type CertificateSubjectUniqueIDSecret struct {
|
|||
UniqueIDSecret []byte `json:"uniqueIdSecret,omitempty"`
|
||||
}
|
||||
|
||||
// LocalCertificate combines a certificate with its local trust flags.
|
||||
type LocalCertificate struct {
|
||||
Certificate *Certificate `json:"certificate,omitempty"`
|
||||
LocalTrust uint `json:"localTrust"`
|
||||
}
|
||||
|
||||
func certificateErrorToError(cerr int) error {
|
||||
switch cerr {
|
||||
case C.ZT_CERTIFICATE_ERROR_NONE:
|
||||
|
@ -488,6 +495,11 @@ func (c *Certificate) JSON() string {
|
|||
return string(j)
|
||||
}
|
||||
|
||||
// URLSerialNo returns the serial number encoded for use in /cert/### local API URLs.
|
||||
func (c *Certificate) URLSerialNo() string {
|
||||
return base64.URLEncoding.EncodeToString(c.SerialNo)
|
||||
}
|
||||
|
||||
// NewCertificateSubjectUniqueId creates a new certificate subject unique ID and corresponding private key.
|
||||
// Right now only one type is supported: CertificateUniqueIdTypeNistP384
|
||||
func NewCertificateSubjectUniqueId(uniqueIdType int) (id []byte, priv []byte, err error) {
|
||||
|
|
|
@ -519,7 +519,7 @@ func (n *Node) TryPeer(fpOrAddress interface{}, ep *Endpoint, retries int) bool
|
|||
}
|
||||
|
||||
// ListCertificates lists certificates and their corresponding local trust flags.
|
||||
func (n *Node) ListCertificates() (certs []*Certificate, localTrust []uint, err error) {
|
||||
func (n *Node) ListCertificates() (certs []LocalCertificate, err error) {
|
||||
cl := C.ZT_Node_listCertificates(n.zn)
|
||||
if cl != nil {
|
||||
defer C.ZT_freeQueryResult(unsafe.Pointer(cl))
|
||||
|
@ -527,15 +527,22 @@ func (n *Node) ListCertificates() (certs []*Certificate, localTrust []uint, err
|
|||
c := newCertificateFromCCertificate(unsafe.Pointer(uintptr(unsafe.Pointer(cl.certs)) + (i * pointerSize)))
|
||||
if c != nil {
|
||||
lt := *((*C.uint)(unsafe.Pointer(uintptr(unsafe.Pointer(cl.localTrust)) + (i * C.sizeof_int))))
|
||||
certs = append(certs, c)
|
||||
localTrust = append(localTrust, uint(lt))
|
||||
certs = append(certs, LocalCertificate{Certificate: c, LocalTrust: uint(lt)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// AddCertificate adds a certificate to this node's local certificate store (after verification).
|
||||
func (n *Node) AddCertificate(cert *Certificate) error {
|
||||
}
|
||||
|
||||
// DeleteCertificate deletes a certificate from this node's local certificate store.
|
||||
func (n *Node) DeleteCertificate(serialNo []byte) error {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
func (n *Node) runMaintenance() {
|
||||
n.localConfigLock.RLock()
|
||||
|
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
@ -4,6 +4,6 @@ github.com/Microsoft/go-winio/pkg/guid
|
|||
# github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||
github.com/hectane/go-acl
|
||||
github.com/hectane/go-acl/api
|
||||
# golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
|
||||
# golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d
|
||||
golang.org/x/sys/internal/unsafeheader
|
||||
golang.org/x/sys/windows
|
||||
|
|
Loading…
Add table
Reference in a new issue