mirror of
https://github.com/outbackdingo/certificates.git
synced 2026-01-27 10:18:34 +00:00
change provisioners api
* /provisioners -> /provisioners/jwk-set-by-issuer * /provisioners now returns a list of Provisioners
This commit is contained in:
34
api/api.go
34
api/api.go
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/ca-component/provisioner"
|
||||
"github.com/smallstep/cli/crypto/tlsutil"
|
||||
"github.com/smallstep/cli/crypto/x509util"
|
||||
"github.com/smallstep/cli/jose"
|
||||
@@ -46,7 +47,7 @@ type Authority interface {
|
||||
Root(shasum string) (*x509.Certificate, error)
|
||||
Sign(cr *x509.CertificateRequest, opts SignOptions, claims ...Claim) (*x509.Certificate, *x509.Certificate, error)
|
||||
Renew(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error)
|
||||
GetProvisioners() (map[string]*jose.JSONWebKeySet, error)
|
||||
GetProvisioners() ([]*provisioner.Provisioner, error)
|
||||
GetEncryptedKey(kid string) (string, error)
|
||||
}
|
||||
|
||||
@@ -172,10 +173,16 @@ type SignRequest struct {
|
||||
NotBefore time.Time `json:"notBefore"`
|
||||
}
|
||||
|
||||
// ProvisionersResponse is the response object that returns the map of
|
||||
// ProvisionersResponse is the response object that returns the list of
|
||||
// provisioners.
|
||||
type ProvisionersResponse struct {
|
||||
Provisioners map[string]*jose.JSONWebKeySet `json:"provisioners"`
|
||||
Provisioners []*provisioner.Provisioner `json:"provisioners"`
|
||||
}
|
||||
|
||||
// JWKSetByIssuerResponse is the response object that returns the map of
|
||||
// provisioners.
|
||||
type JWKSetByIssuerResponse struct {
|
||||
Map map[string]*jose.JSONWebKeySet `json:"map"`
|
||||
}
|
||||
|
||||
// ProvisionerKeyResponse is the response object that returns the encryptoed key
|
||||
@@ -250,6 +257,7 @@ func (h *caHandler) Route(r Router) {
|
||||
r.MethodFunc("POST", "/renew", h.Renew)
|
||||
r.MethodFunc("GET", "/provisioners", h.Provisioners)
|
||||
r.MethodFunc("GET", "/provisioners/{kid}/encrypted-key", h.ProvisionerKey)
|
||||
r.MethodFunc("GET", "/provisioners/jwk-set-by-issuer", h.JWKSetByIssuer)
|
||||
}
|
||||
|
||||
// Health is an HTTP handler that returns the status of the server.
|
||||
@@ -353,3 +361,23 @@ func (h *caHandler) ProvisionerKey(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
JSON(w, &ProvisionerKeyResponse{key})
|
||||
}
|
||||
|
||||
func (h *caHandler) JWKSetByIssuer(w http.ResponseWriter, r *http.Request) {
|
||||
m := map[string]*jose.JSONWebKeySet{}
|
||||
ps, err := h.Authority.GetProvisioners()
|
||||
if err != nil {
|
||||
WriteError(w, InternalServerError(err))
|
||||
return
|
||||
}
|
||||
for _, p := range ps {
|
||||
ks, found := m[p.Issuer]
|
||||
if found {
|
||||
ks.Keys = append(ks.Keys, *p.Key)
|
||||
} else {
|
||||
ks = new(jose.JSONWebKeySet)
|
||||
ks.Keys = []jose.JSONWebKey{*p.Key}
|
||||
m[p.Issuer] = ks
|
||||
}
|
||||
}
|
||||
JSON(w, &JWKSetByIssuerResponse{m})
|
||||
}
|
||||
|
||||
104
api/api_test.go
104
api/api_test.go
@@ -17,6 +17,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/smallstep/ca-component/provisioner"
|
||||
"github.com/smallstep/cli/crypto/tlsutil"
|
||||
"github.com/smallstep/cli/jose"
|
||||
)
|
||||
@@ -397,7 +398,7 @@ type mockAuthority struct {
|
||||
root func(shasum string) (*x509.Certificate, error)
|
||||
sign func(cr *x509.CertificateRequest, opts SignOptions, claims ...Claim) (*x509.Certificate, *x509.Certificate, error)
|
||||
renew func(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error)
|
||||
getProvisioners func() (map[string]*jose.JSONWebKeySet, error)
|
||||
getProvisioners func() ([]*provisioner.Provisioner, error)
|
||||
getEncryptedKey func(kid string) (string, error)
|
||||
}
|
||||
|
||||
@@ -444,11 +445,11 @@ func (m *mockAuthority) Renew(cert *x509.Certificate) (*x509.Certificate, *x509.
|
||||
return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err
|
||||
}
|
||||
|
||||
func (m *mockAuthority) GetProvisioners() (map[string]*jose.JSONWebKeySet, error) {
|
||||
func (m *mockAuthority) GetProvisioners() ([]*provisioner.Provisioner, error) {
|
||||
if m.getProvisioners != nil {
|
||||
return m.getProvisioners()
|
||||
}
|
||||
return m.ret1.(map[string]*jose.JSONWebKeySet), m.err
|
||||
return m.ret1.([]*provisioner.Provisioner), m.err
|
||||
}
|
||||
|
||||
func (m *mockAuthority) GetEncryptedKey(kid string) (string, error) {
|
||||
@@ -670,6 +671,82 @@ func Test_caHandler_Renew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_caHandler_JWKSetByIssuer(t *testing.T) {
|
||||
type fields struct {
|
||||
Authority Authority
|
||||
}
|
||||
type args struct {
|
||||
w http.ResponseWriter
|
||||
r *http.Request
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", "http://example.com/provisioners/jwk-set-by-issuer", nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var key jose.JSONWebKey
|
||||
if err := json.Unmarshal([]byte(pubKey), &key); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := []*provisioner.Provisioner{
|
||||
&provisioner.Provisioner{
|
||||
Issuer: "p1",
|
||||
Key: &key,
|
||||
},
|
||||
&provisioner.Provisioner{
|
||||
Issuer: "p2",
|
||||
Key: &key,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
statusCode int
|
||||
}{
|
||||
{"ok", fields{&mockAuthority{ret1: p}}, args{httptest.NewRecorder(), req}, 200},
|
||||
{"fail", fields{&mockAuthority{ret1: p, err: fmt.Errorf("the error")}}, args{httptest.NewRecorder(), req}, 500},
|
||||
}
|
||||
|
||||
expectedKey, err := json.Marshal(key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := []byte(`{"map":{"p1":{"keys":[` + string(expectedKey) + `]},"p2":{"keys":[` + string(expectedKey) + `]}}}`)
|
||||
expectedError := []byte(`{"status":500,"message":"Internal Server Error"}`)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
h := &caHandler{
|
||||
Authority: tt.fields.Authority,
|
||||
}
|
||||
h.JWKSetByIssuer(tt.args.w, tt.args.r)
|
||||
|
||||
rec := tt.args.w.(*httptest.ResponseRecorder)
|
||||
res := rec.Result()
|
||||
if res.StatusCode != tt.statusCode {
|
||||
t.Errorf("caHandler.JWKSetByIssuer StatusCode = %d, wants %d", res.StatusCode, tt.statusCode)
|
||||
}
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
if err != nil {
|
||||
t.Errorf("caHandler.JWKSetByIssuer unexpected error = %v", err)
|
||||
}
|
||||
if tt.statusCode < http.StatusBadRequest {
|
||||
if !bytes.Equal(bytes.TrimSpace(body), expected) {
|
||||
t.Errorf("caHandler.JWKSetByIssuer Body = %s, wants %s", body, expected)
|
||||
}
|
||||
} else {
|
||||
if !bytes.Equal(bytes.TrimSpace(body), expectedError) {
|
||||
t.Errorf("caHandler.JWKSetByIssuer Body = %s, wants %s", body, expectedError)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_caHandler_Provisioners(t *testing.T) {
|
||||
type fields struct {
|
||||
Authority Authority
|
||||
@@ -689,14 +766,21 @@ func Test_caHandler_Provisioners(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := map[string]*jose.JSONWebKeySet{
|
||||
"p1": &jose.JSONWebKeySet{
|
||||
Keys: []jose.JSONWebKey{key},
|
||||
p := []*provisioner.Provisioner{
|
||||
&provisioner.Provisioner{
|
||||
Type: "JWK",
|
||||
Issuer: "max",
|
||||
EncryptedKey: "abc",
|
||||
Key: &key,
|
||||
},
|
||||
"p2": &jose.JSONWebKeySet{
|
||||
Keys: []jose.JSONWebKey{key},
|
||||
&provisioner.Provisioner{
|
||||
Type: "JWK",
|
||||
Issuer: "mariano",
|
||||
EncryptedKey: "def",
|
||||
Key: &key,
|
||||
},
|
||||
}
|
||||
pr := ProvisionersResponse{p}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -708,11 +792,11 @@ func Test_caHandler_Provisioners(t *testing.T) {
|
||||
{"fail", fields{&mockAuthority{ret1: p, err: fmt.Errorf("the error")}}, args{httptest.NewRecorder(), req}, 500},
|
||||
}
|
||||
|
||||
expectedKey, err := json.Marshal(key)
|
||||
expected, err := json.Marshal(pr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected := []byte(`{"provisioners":{"p1":{"keys":[` + string(expectedKey) + `]},"p2":{"keys":[` + string(expectedKey) + `]}}}`)
|
||||
|
||||
expectedError := []byte(`{"status":500,"message":"Internal Server Error"}`)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user