forked from TrueCloudLab/certificates
Add identity client and move identity to a new package.
This commit is contained in:
parent
89b216c21e
commit
0d9a9e083e
19 changed files with 667 additions and 86 deletions
36
ca/client.go
36
ca/client.go
|
@ -25,13 +25,18 @@ import (
|
|||
"github.com/smallstep/certificates/api"
|
||||
"github.com/smallstep/certificates/authority"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/ca/identity"
|
||||
"github.com/smallstep/cli/config"
|
||||
"github.com/smallstep/cli/crypto/keys"
|
||||
"github.com/smallstep/cli/crypto/pemutil"
|
||||
"github.com/smallstep/cli/crypto/x509util"
|
||||
"golang.org/x/net/http2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
// DisableIdentity is a global variable to disable the identity.
|
||||
var DisableIdentity = false
|
||||
|
||||
// UserAgent will set the User-Agent header in the client requests.
|
||||
var UserAgent = "step-http-client/1.0"
|
||||
|
||||
|
@ -120,26 +125,18 @@ func (o *clientOptions) applyDefaultIdentity() error {
|
|||
}
|
||||
|
||||
// Do not load an identity if something fails
|
||||
b, err := ioutil.ReadFile(IdentityFile)
|
||||
i, err := identity.LoadDefaultIdentity()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var identity Identity
|
||||
if err := json.Unmarshal(b, &identity); err != nil {
|
||||
if err := i.Validate(); err != nil {
|
||||
return nil
|
||||
}
|
||||
if err := identity.Validate(); err != nil {
|
||||
return nil
|
||||
}
|
||||
opts, err := identity.Options()
|
||||
crt, err := i.TLSCertificate()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, fn := range opts {
|
||||
if err := fn(o); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
o.certificate = crt
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1111,6 +1108,21 @@ func CreateCertificateRequest(commonName string, sans ...string) (*api.Certifica
|
|||
return createCertificateRequest(commonName, sans, key)
|
||||
}
|
||||
|
||||
// CreateIdentityRequest returns a new CSR to create the identity. If an
|
||||
// identity was already present it reuses the private key.
|
||||
func CreateIdentityRequest(commonName string, sans ...string) (*api.CertificateRequest, crypto.PrivateKey, error) {
|
||||
var identityKey crypto.PrivateKey
|
||||
if i, err := identity.LoadDefaultIdentity(); err == nil && i.Key != "" {
|
||||
if k, err := pemutil.Read(i.Key); err == nil {
|
||||
identityKey = k
|
||||
}
|
||||
}
|
||||
if identityKey == nil {
|
||||
return CreateCertificateRequest(commonName, sans...)
|
||||
}
|
||||
return createCertificateRequest(commonName, sans, identityKey)
|
||||
}
|
||||
|
||||
func createCertificateRequest(commonName string, sans []string, key crypto.PrivateKey) (*api.CertificateRequest, crypto.PrivateKey, error) {
|
||||
if len(sans) == 0 {
|
||||
sans = []string{commonName}
|
||||
|
|
105
ca/identity/client.go
Normal file
105
ca/identity/client.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
package identity
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Client wraps http.Client with a transport using the step root and identity.
|
||||
type Client struct {
|
||||
CaURL *url.URL
|
||||
*http.Client
|
||||
}
|
||||
|
||||
// ResolveReference resolves the given reference from the CaURL.
|
||||
func (c *Client) ResolveReference(ref *url.URL) *url.URL {
|
||||
return c.CaURL.ResolveReference(ref)
|
||||
}
|
||||
|
||||
// LoadStepClient configures an http.Client with the root in
|
||||
// $STEPPATH/config/defaults.json and the identity defined in
|
||||
// $STEPPATH/config/identity.json
|
||||
func LoadClient() (*Client, error) {
|
||||
b, err := ioutil.ReadFile(DefaultsFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading %s", DefaultsFile)
|
||||
}
|
||||
|
||||
var defaults defaultsConfig
|
||||
if err := json.Unmarshal(b, &defaults); err != nil {
|
||||
return nil, errors.Wrapf(err, "error unmarshaling %s", DefaultsFile)
|
||||
}
|
||||
if err := defaults.Validate(); err != nil {
|
||||
return nil, errors.Wrapf(err, "error validating %s", DefaultsFile)
|
||||
}
|
||||
caURL, err := url.Parse(defaults.CaURL)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error validating %s", DefaultsFile)
|
||||
}
|
||||
if caURL.Scheme == "" {
|
||||
caURL.Scheme = "https"
|
||||
}
|
||||
|
||||
identity, err := LoadDefaultIdentity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := identity.Validate(); err != nil {
|
||||
return nil, errors.Wrapf(err, "error validating %s", IdentityFile)
|
||||
}
|
||||
if kind := identity.Kind(); kind != MutualTLS {
|
||||
return nil, errors.Errorf("unsupported identity %s: only mTLS is currently supported", kind)
|
||||
}
|
||||
|
||||
// Prepare transport with information in defaults.json and identity.json
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{}
|
||||
|
||||
// RootCAs
|
||||
b, err = ioutil.ReadFile(defaults.Root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error loading %s", defaults.Root)
|
||||
}
|
||||
pool := x509.NewCertPool()
|
||||
if pool.AppendCertsFromPEM(b) {
|
||||
tr.TLSClientConfig.RootCAs = pool
|
||||
}
|
||||
|
||||
// Certificate
|
||||
crt, err := tls.LoadX509KeyPair(identity.Certificate, identity.Key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading certificate: %v", err)
|
||||
}
|
||||
tr.TLSClientConfig.Certificates = []tls.Certificate{crt}
|
||||
|
||||
return &Client{
|
||||
CaURL: caURL,
|
||||
Client: &http.Client{
|
||||
Transport: tr,
|
||||
},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
type defaultsConfig struct {
|
||||
CaURL string `json:"ca-url"`
|
||||
Root string `json:"root"`
|
||||
}
|
||||
|
||||
func (c *defaultsConfig) Validate() error {
|
||||
switch {
|
||||
case c.CaURL == "":
|
||||
return fmt.Errorf("missing or invalid `ca-url` property")
|
||||
case c.Root == "":
|
||||
return fmt.Errorf("missing or invalid `root` property")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
133
ca/identity/client_test.go
Normal file
133
ca/identity/client_test.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
package identity
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestClient_ResolveReference(t *testing.T) {
|
||||
type fields struct {
|
||||
CaURL *url.URL
|
||||
}
|
||||
type args struct {
|
||||
ref *url.URL
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want *url.URL
|
||||
}{
|
||||
{"ok", fields{&url.URL{Scheme: "https", Host: "localhost"}}, args{&url.URL{Path: "/foo"}}, &url.URL{Scheme: "https", Host: "localhost", Path: "/foo"}},
|
||||
{"ok", fields{&url.URL{Scheme: "https", Host: "localhost", Path: "/bar"}}, args{&url.URL{Path: "/foo"}}, &url.URL{Scheme: "https", Host: "localhost", Path: "/foo"}},
|
||||
{"ok", fields{&url.URL{Scheme: "https", Host: "localhost"}}, args{&url.URL{Path: "/foo", RawQuery: "foo=bar"}}, &url.URL{Scheme: "https", Host: "localhost", Path: "/foo", RawQuery: "foo=bar"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Client{
|
||||
CaURL: tt.fields.CaURL,
|
||||
}
|
||||
if got := c.ResolveReference(tt.args.ref); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Client.ResolveReference() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadClient(t *testing.T) {
|
||||
oldIdentityFile := IdentityFile
|
||||
oldDefaultsFile := DefaultsFile
|
||||
defer func() {
|
||||
IdentityFile = oldIdentityFile
|
||||
DefaultsFile = oldDefaultsFile
|
||||
}()
|
||||
|
||||
crt, err := tls.LoadX509KeyPair("testdata/identity/identity.crt", "testdata/identity/identity_key")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b, err := ioutil.ReadFile("testdata/certs/root_ca.crt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pool := x509.NewCertPool()
|
||||
pool.AppendCertsFromPEM(b)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{
|
||||
Certificates: []tls.Certificate{crt},
|
||||
RootCAs: pool,
|
||||
}
|
||||
expected := &Client{
|
||||
CaURL: &url.URL{Scheme: "https", Host: "127.0.0.1"},
|
||||
Client: &http.Client{
|
||||
Transport: tr,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare func()
|
||||
want *Client
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", func() { IdentityFile = "testdata/config/identity.json"; DefaultsFile = "testdata/config/defaults.json" }, expected, false},
|
||||
{"fail identity", func() { IdentityFile = "testdata/config/missing.json"; DefaultsFile = "testdata/config/defaults.json" }, nil, true},
|
||||
{"fail identity", func() { IdentityFile = "testdata/config/fail.json"; DefaultsFile = "testdata/config/defaults.json" }, nil, true},
|
||||
{"fail defaults", func() { IdentityFile = "testdata/config/identity.json"; DefaultsFile = "testdata/config/missing.json" }, nil, true},
|
||||
{"fail defaults", func() { IdentityFile = "testdata/config/identity.json"; DefaultsFile = "testdata/config/fail.json" }, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.prepare()
|
||||
got, err := LoadClient()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("LoadClient() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if tt.want == nil {
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("LoadClient() = %#v, want %#v", got, tt.want)
|
||||
}
|
||||
} else {
|
||||
if !reflect.DeepEqual(got.CaURL, tt.want.CaURL) ||
|
||||
!reflect.DeepEqual(got.Client.Transport.(*http.Transport).TLSClientConfig.RootCAs, tt.want.Client.Transport.(*http.Transport).TLSClientConfig.RootCAs) ||
|
||||
!reflect.DeepEqual(got.Client.Transport.(*http.Transport).TLSClientConfig.Certificates, tt.want.Client.Transport.(*http.Transport).TLSClientConfig.Certificates) {
|
||||
t.Errorf("LoadClient() = %#v, want %#v", got, tt.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_defaultsConfig_Validate(t *testing.T) {
|
||||
type fields struct {
|
||||
CaURL string
|
||||
Root string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{"https://127.0.0.1", "root_ca.crt"}, false},
|
||||
{"fail ca-url", fields{"", "root_ca.crt"}, true},
|
||||
{"fail root", fields{"https://127.0.0.1", ""}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &defaultsConfig{
|
||||
CaURL: tt.fields.CaURL,
|
||||
Root: tt.fields.Root,
|
||||
}
|
||||
if err := c.Validate(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("defaultsConfig.Validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ca
|
||||
package identity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -8,7 +8,6 @@ import (
|
|||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -20,17 +19,14 @@ import (
|
|||
"github.com/smallstep/cli/crypto/pemutil"
|
||||
)
|
||||
|
||||
// IdentityType represents the different types of identity files.
|
||||
type IdentityType string
|
||||
|
||||
// DisableIdentity is a global variable to disable the identity.
|
||||
var DisableIdentity = false
|
||||
// Type represents the different types of identity files.
|
||||
type Type string
|
||||
|
||||
// Disabled represents a disabled identity type
|
||||
const Disabled IdentityType = ""
|
||||
const Disabled Type = ""
|
||||
|
||||
// MutualTLS represents the identity using mTLS
|
||||
const MutualTLS IdentityType = "mTLS"
|
||||
const MutualTLS Type = "mTLS"
|
||||
|
||||
// DefaultLeeway is the duration for matching not before claims.
|
||||
const DefaultLeeway = 1 * time.Minute
|
||||
|
@ -38,6 +34,9 @@ const DefaultLeeway = 1 * time.Minute
|
|||
// IdentityFile contains the location of the identity file.
|
||||
var IdentityFile = filepath.Join(config.StepPath(), "config", "identity.json")
|
||||
|
||||
// DefaultsFile contains the location of the defaults file.
|
||||
var DefaultsFile = filepath.Join(config.StepPath(), "config", "defaults.json")
|
||||
|
||||
// Identity represents the identity file that can be used to authenticate with
|
||||
// the CA.
|
||||
type Identity struct {
|
||||
|
@ -46,26 +45,11 @@ type Identity struct {
|
|||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// NewIdentityRequest returns a new CSR to create the identity. If an identity
|
||||
// was already present it reuses the private key.
|
||||
func NewIdentityRequest(commonName string, sans ...string) (*api.CertificateRequest, crypto.PrivateKey, error) {
|
||||
var identityKey crypto.PrivateKey
|
||||
if i, err := LoadDefaultIdentity(); err == nil && i.Key != "" {
|
||||
if k, err := pemutil.Read(i.Key); err == nil {
|
||||
identityKey = k
|
||||
}
|
||||
}
|
||||
if identityKey == nil {
|
||||
return CreateCertificateRequest(commonName, sans...)
|
||||
}
|
||||
return createCertificateRequest(commonName, sans, identityKey)
|
||||
}
|
||||
|
||||
// LoadDefaultIdentity loads the default identity.
|
||||
func LoadDefaultIdentity() (*Identity, error) {
|
||||
b, err := ioutil.ReadFile(IdentityFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error reading identity json")
|
||||
return nil, errors.Wrapf(err, "error reading %s", IdentityFile)
|
||||
}
|
||||
identity := new(Identity)
|
||||
if err := json.Unmarshal(b, &identity); err != nil {
|
||||
|
@ -137,14 +121,14 @@ func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) er
|
|||
}
|
||||
|
||||
// Kind returns the type for the given identity.
|
||||
func (i *Identity) Kind() IdentityType {
|
||||
func (i *Identity) Kind() Type {
|
||||
switch strings.ToLower(i.Type) {
|
||||
case "":
|
||||
return Disabled
|
||||
case "mtls":
|
||||
return MutualTLS
|
||||
default:
|
||||
return IdentityType(i.Type)
|
||||
return Type(i.Type)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,74 +144,55 @@ func (i *Identity) Validate() error {
|
|||
if i.Key == "" {
|
||||
return errors.New("identity.key cannot be empty")
|
||||
}
|
||||
if err := fileExists(i.Certificate); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileExists(i.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("unsupported identity type %s", i.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// Options returns the ClientOptions used for the given identity.
|
||||
func (i *Identity) Options() ([]ClientOption, error) {
|
||||
// TLSCertificate returns a tls.Certificate for the identity.
|
||||
func (i *Identity) TLSCertificate() (tls.Certificate, error) {
|
||||
fail := func(err error) (tls.Certificate, error) { return tls.Certificate{}, err }
|
||||
switch i.Kind() {
|
||||
case Disabled:
|
||||
return nil, nil
|
||||
return tls.Certificate{}, nil
|
||||
case MutualTLS:
|
||||
crt, err := tls.LoadX509KeyPair(i.Certificate, i.Key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating identity certificate")
|
||||
return fail(errors.Wrap(err, "error creating identity certificate"))
|
||||
}
|
||||
|
||||
// Check if certificate is expired.
|
||||
// Do not return any options if expired.
|
||||
x509Cert, err := x509.ParseCertificate(crt.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating identity certificate")
|
||||
return fail(errors.Wrap(err, "error creating identity certificate"))
|
||||
}
|
||||
now := time.Now().Truncate(time.Second)
|
||||
if now.Add(DefaultLeeway).Before(x509Cert.NotBefore) || now.After(x509Cert.NotAfter) {
|
||||
return nil, nil
|
||||
if now.Add(DefaultLeeway).Before(x509Cert.NotBefore) {
|
||||
return fail(errors.New("certificate is not yet valid"))
|
||||
}
|
||||
return []ClientOption{WithCertificate(crt)}, nil
|
||||
if now.After(x509Cert.NotAfter) {
|
||||
return fail(errors.New("certificate is already expired"))
|
||||
}
|
||||
return crt, nil
|
||||
default:
|
||||
return nil, errors.Errorf("unsupported identity type %s", i.Type)
|
||||
return fail(errors.Errorf("unsupported identity type %s", i.Type))
|
||||
}
|
||||
}
|
||||
|
||||
// Renew renews the identity certificate using the given client.
|
||||
func (i *Identity) Renew(client *Client) error {
|
||||
switch i.Kind() {
|
||||
case Disabled:
|
||||
return nil
|
||||
case MutualTLS:
|
||||
cert, err := tls.LoadX509KeyPair(i.Certificate, i.Key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating identity certificate")
|
||||
}
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: client.GetRootCAs(),
|
||||
PreferServerCipherSuites: true,
|
||||
},
|
||||
}
|
||||
resp, err := client.Renew(tr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
for _, crt := range resp.CertChainPEM {
|
||||
block := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: crt.Raw,
|
||||
}
|
||||
if err := pem.Encode(buf, block); err != nil {
|
||||
return errors.Wrap(err, "error encoding identity certificate")
|
||||
}
|
||||
}
|
||||
if err := ioutil.WriteFile(i.Certificate, buf.Bytes(), 0600); err != nil {
|
||||
return errors.Wrap(err, "error writing identity certificate")
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf("unsupported identity type %s", i.Type)
|
||||
func fileExists(filename string) error {
|
||||
info, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error reading %s", filename)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return errors.Errorf("error reading %s: file is a directory", filename)
|
||||
}
|
||||
return nil
|
||||
}
|
166
ca/identity/identity_test.go
Normal file
166
ca/identity/identity_test.go
Normal file
|
@ -0,0 +1,166 @@
|
|||
package identity
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadDefaultIdentity(t *testing.T) {
|
||||
oldFile := IdentityFile
|
||||
defer func() {
|
||||
IdentityFile = oldFile
|
||||
}()
|
||||
|
||||
expected := &Identity{
|
||||
Type: "mTLS",
|
||||
Certificate: "testdata/identity/identity.crt",
|
||||
Key: "testdata/identity/identity_key",
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare func()
|
||||
want *Identity
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", func() { IdentityFile = "testdata/config/identity.json" }, expected, false},
|
||||
{"fail read", func() { IdentityFile = "testdata/config/missing.json" }, nil, true},
|
||||
{"fail unmarshal", func() { IdentityFile = "testdata/config/fail.json" }, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.prepare()
|
||||
got, err := LoadDefaultIdentity()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("LoadDefaultIdentity() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("LoadDefaultIdentity() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentity_Kind(t *testing.T) {
|
||||
type fields struct {
|
||||
Type string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want Type
|
||||
}{
|
||||
{"disabled", fields{""}, Disabled},
|
||||
{"mutualTLS", fields{"mTLS"}, MutualTLS},
|
||||
{"unknown", fields{"unknown"}, Type("unknown")},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
i := &Identity{
|
||||
Type: tt.fields.Type,
|
||||
}
|
||||
if got := i.Kind(); got != tt.want {
|
||||
t.Errorf("Identity.Kind() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentity_Validate(t *testing.T) {
|
||||
type fields struct {
|
||||
Type string
|
||||
Certificate string
|
||||
Key string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{"mTLS", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, false},
|
||||
{"ok disabled", fields{}, false},
|
||||
{"fail type", fields{"foo", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, true},
|
||||
{"fail certificate", fields{"mTLS", "", "testdata/identity/identity_key"}, true},
|
||||
{"fail key", fields{"mTLS", "testdata/identity/identity.crt", ""}, true},
|
||||
{"fail missing certificate", fields{"mTLS", "testdata/identity/missing.crt", "testdata/identity/identity_key"}, true},
|
||||
{"fail missing key", fields{"mTLS", "testdata/identity/identity.crt", "testdata/identity/missing_key"}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
i := &Identity{
|
||||
Type: tt.fields.Type,
|
||||
Certificate: tt.fields.Certificate,
|
||||
Key: tt.fields.Key,
|
||||
}
|
||||
if err := i.Validate(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Identity.Validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentity_TLSCertificate(t *testing.T) {
|
||||
expected, err := tls.LoadX509KeyPair("testdata/identity/identity.crt", "testdata/identity/identity_key")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
Type string
|
||||
Certificate string
|
||||
Key string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want tls.Certificate
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{"mTLS", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, expected, false},
|
||||
{"ok disabled", fields{}, tls.Certificate{}, false},
|
||||
{"fail type", fields{"foo", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, tls.Certificate{}, true},
|
||||
{"fail certificate", fields{"mTLS", "testdata/certs/server.crt", "testdata/identity/identity_key"}, tls.Certificate{}, true},
|
||||
{"fail not after", fields{"mTLS", "testdata/identity/expired.crt", "testdata/identity/identity_key"}, tls.Certificate{}, true},
|
||||
{"fail not before", fields{"mTLS", "testdata/identity/not_before.crt", "testdata/identity/identity_key"}, tls.Certificate{}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
i := &Identity{
|
||||
Type: tt.fields.Type,
|
||||
Certificate: tt.fields.Certificate,
|
||||
Key: tt.fields.Key,
|
||||
}
|
||||
got, err := i.TLSCertificate()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Identity.TLSCertificate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Identity.TLSCertificate() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_fileExists(t *testing.T) {
|
||||
type args struct {
|
||||
filename string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", args{"testdata/identity/identity.crt"}, false},
|
||||
{"missing", args{"testdata/identity/missing.crt"}, true},
|
||||
{"directory", args{"testdata/identity"}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := fileExists(tt.args.filename); (err != nil) != tt.wantErr {
|
||||
t.Errorf("fileExists() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
11
ca/identity/testdata/certs/intermediate_ca.crt
vendored
Normal file
11
ca/identity/testdata/certs/intermediate_ca.crt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBozCCAUqgAwIBAgIQF4UYp5uEiuq/BO0cOWTq9DAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
|
||||
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQGECLvDj+ZSqW78DRmUaugh0EU4NQ5
|
||||
PoZxsLpB0gUsvNDGE0V5/2Q85GmsYzlBjBuoM+RfvF2fSP+dDTs3Hwjgo2YwZDAO
|
||||
BgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU95Au
|
||||
B82vrt2UJyDTNBQH3B8sePUwHwYDVR0jBBgwFoAUgwZucvb+H/1chTPLQ1GYTJwK
|
||||
CXQwCgYIKoZIzj0EAwIDRwAwRAIgSaHuI61rNsFf1ke5WSUyuqy51DIE/ONCSWKT
|
||||
VQgTVJMCIAMsE+Eibk43hL4qQi5vBJiFLfGQDDN/9HUi6w4w5EZ7
|
||||
-----END CERTIFICATE-----
|
10
ca/identity/testdata/certs/root_ca.crt
vendored
Normal file
10
ca/identity/testdata/certs/root_ca.crt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBfDCCASGgAwIBAgIQE8W0gyMruWxRDfegdPHrdDAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMBwxGjAYBgNVBAMTEVNtYWxsc3RlcCBSb290IENBMFkwEwYHKoZI
|
||||
zj0CAQYIKoZIzj0DAQcDQgAEgd74QbUDcEj3aV5Oxv5eAMzwnejj7S/iDFAp89t9
|
||||
kEb+Ux4NZC3Pay+92yRL//dBUI5WOopLXBniYomH4SFJg6NFMEMwDgYDVR0PAQH/
|
||||
BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFIMGbnL2/h/9XIUz
|
||||
y0NRmEycCgl0MAoGCCqGSM49BAMCA0kAMEYCIQD3/IUBL5/9Hpdp2+t4XnA42cwQ
|
||||
j5WkGY5hJIhdQ5P8qgIhAMf19nAIUlSbXKPf21Gv6eYEoNuuLfpcqnfBt5NJX64M
|
||||
-----END CERTIFICATE-----
|
25
ca/identity/testdata/certs/server.crt
vendored
Normal file
25
ca/identity/testdata/certs/server.crt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICHDCCAcKgAwIBAgIQQ4n25nGGKm6uGyVQ4cDNCTAKBggqhkjOPQQDAjAkMSIw
|
||||
IAYDVQQDExlTbWFsbHN0ZXAgSW50ZXJtZWRpYXRlIENBMB4XDTE5MTIxMjAyNTAz
|
||||
OVoXDTI5MTIwOTAyNTAzOVowFjEUMBIGA1UEAxMLdGVzdCBzZXJ2ZXIwWTATBgcq
|
||||
hkjOPQIBBggqhkjOPQMBBwNCAATmQRMCzRP1hBcYhAXlbiyR9QtsQosQfCZTS+en
|
||||
g6TtL9VjWsQXqd1SSStfi0grPyiTQLIPhPbSho/VJzSpf59Do4HjMIHgMA4GA1Ud
|
||||
DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0O
|
||||
BBYEFBvz34jDFrb3G4qiGkZZj99BnabAMB8GA1UdIwQYMBaAFPeQLgfNr67dlCcg
|
||||
0zQUB9wfLHj1MBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATBTBgwrBgEEAYKk
|
||||
ZMYoQAEEQzBBAgEBBA9qb2VAZXhhbXBsZS5jb20EKzJ3U05fQ21leFhXaWdfRG5w
|
||||
VlpzWUZkTUgxU3RjODZCSUJ6TjBydDVpcEUwCgYIKoZIzj0EAwIDSAAwRQIhAOt6
|
||||
/x9LWQyBtx3RcyyALF2//OCfGjAx0zLGmUsXIHGIAiAZGVwTxbhxiYU95AXncS3F
|
||||
3tXNaaIJyyO7atiVPhCR1A==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBozCCAUqgAwIBAgIQF4UYp5uEiuq/BO0cOWTq9DAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
|
||||
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQGECLvDj+ZSqW78DRmUaugh0EU4NQ5
|
||||
PoZxsLpB0gUsvNDGE0V5/2Q85GmsYzlBjBuoM+RfvF2fSP+dDTs3Hwjgo2YwZDAO
|
||||
BgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU95Au
|
||||
B82vrt2UJyDTNBQH3B8sePUwHwYDVR0jBBgwFoAUgwZucvb+H/1chTPLQ1GYTJwK
|
||||
CXQwCgYIKoZIzj0EAwIDRwAwRAIgSaHuI61rNsFf1ke5WSUyuqy51DIE/ONCSWKT
|
||||
VQgTVJMCIAMsE+Eibk43hL4qQi5vBJiFLfGQDDN/9HUi6w4w5EZ7
|
||||
-----END CERTIFICATE-----
|
41
ca/identity/testdata/config/ca.json
vendored
Normal file
41
ca/identity/testdata/config/ca.json
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"root": "testdata/certs/root_ca.crt",
|
||||
"federatedRoots": [],
|
||||
"crt": "testdata/certs/intermediate_ca.crt",
|
||||
"key": "testdata/secrets/intermediate_ca_key",
|
||||
"address": ":443",
|
||||
"dnsNames": [
|
||||
"127.0.0.1",
|
||||
"localhost"
|
||||
],
|
||||
"logger": {
|
||||
"format": "text"
|
||||
},
|
||||
"authority": {
|
||||
"provisioners": [
|
||||
{
|
||||
"type": "jwk",
|
||||
"name": "joe@example.com",
|
||||
"key": {
|
||||
"use": "sig",
|
||||
"kty": "EC",
|
||||
"kid": "2wSN_CmexXWig_DnpVZsYFdMH1Stc86BIBzN0rt5ipE",
|
||||
"crv": "P-256",
|
||||
"alg": "ES256",
|
||||
"x": "QqYaIULUQqP0EOmogorCcQIxEtI7-zCRcUVFxyNwq4Q",
|
||||
"y": "YeIMipM7uMHjlxpFIUbfCBC1xEXczXNYRzJCMyrGcH0"
|
||||
},
|
||||
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiSVQ3MVNUMTNNMTd1S3Y4VHRDczYyUSJ9.TXShNLPcITS0bFvQeMjjCDhQLICQs1ShECkgUkUsAm9ZWpSq6Yu03w.SWxtxscivS3L5Yo5.O-XY9YKK8wEJgVs7X1-FxiM_6w4s7iJQNXRD2JrZRsXtDqUz7diPfXuBOFPUFsNzykvob1qCsU4B23Ek2nbaS2HqPrIOGbOvOsR8Pt6kNoraH1QDp3Hyzkv0S-VGM0MCGYDDmmH33PZmsdS36Aw8v9xBnDHlwlMg4NjTskxpqggfQl01433B0lCJqJdrmeBeGL1ZCKixvc-wAQxU8GH5iiD925ViLY7RlVo-tmIBXpxRgheLgKiuMxmgPvf15qCdgU5TRqeuJbYJLzvPpoai0W4WHjpM1zLjjmp5OYRFW4m4ZRZf5g1Cm4lstFPUlTn85fkMZFdBh4_bFbjAv7k.epXp8DZKHj_dxP9EohwDIg"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tls": {
|
||||
"cipherSuites": [
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
||||
],
|
||||
"minVersion": 1.2,
|
||||
"maxVersion": 1.2,
|
||||
"renegotiation": false
|
||||
}
|
||||
}
|
6
ca/identity/testdata/config/defaults.json
vendored
Normal file
6
ca/identity/testdata/config/defaults.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"ca-url": "https://127.0.0.1",
|
||||
"ca-config": "testdata/config/ca.json",
|
||||
"fingerprint": "9dc35eef23a234b2520516a3169090d7ec2fc61323bdd6e4fde08bcfec5d0931",
|
||||
"root": "testdata/certs/root_ca.crt"
|
||||
}
|
1
ca/identity/testdata/config/fail.json
vendored
Normal file
1
ca/identity/testdata/config/fail.json
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
This is not a json file
|
5
ca/identity/testdata/config/identity.json
vendored
Normal file
5
ca/identity/testdata/config/identity.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type": "mTLS",
|
||||
"crt": "testdata/identity/identity.crt",
|
||||
"key": "testdata/identity/identity_key"
|
||||
}
|
25
ca/identity/testdata/identity/expired.crt
vendored
Normal file
25
ca/identity/testdata/identity/expired.crt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICIDCCAcegAwIBAgIRAM1GK1TLmvWLVOjP0dqVCiEwCgYIKoZIzj0EAwIwJDEi
|
||||
MCAGA1UEAxMZU21hbGxzdGVwIEludGVybWVkaWF0ZSBDQTAeFw0xODEyMTIwMzI2
|
||||
MzZaFw0xODEyMTMwMzI2MzZaMBoxGDAWBgNVBAMMD2pvZUBleGFtcGxlLmNvbTBZ
|
||||
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABI0+NSjg3+vGhAeZGrxPksrXFqq0AIUB
|
||||
D3nQPmGPuUWIEmbt6qp3EVF/o+KwzWgDv5fzBmDlBkdBRz9xc3XIcQ2jgeMwgeAw
|
||||
HwYDVR0jBBgwFoAU95AuB82vrt2UJyDTNBQH3B8sePUwDgYDVR0PAQH/BAQDAgWg
|
||||
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU1Ht6zX2M
|
||||
eVXcnxhM4hxU0RCblNowGgYDVR0RBBMwEYEPam9lQGV4YW1wbGUuY29tMFMGDCsG
|
||||
AQQBgqRkxihAAQRDMEECAQEED2pvZUBleGFtcGxlLmNvbQQrMndTTl9DbWV4WFdp
|
||||
Z19EbnBWWnNZRmRNSDFTdGM4NkJJQnpOMHJ0NWlwRTAKBggqhkjOPQQDAgNHADBE
|
||||
AiBgoPACCRJ6s+C5Yz3BWeyM6VnWewctnaMsVJKyPdb98AIgV/7HRZsc5Xgi8iVt
|
||||
D4XxVOZDu/y1V4VIH5W4INfg6JA=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBozCCAUqgAwIBAgIQF4UYp5uEiuq/BO0cOWTq9DAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
|
||||
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQGECLvDj+ZSqW78DRmUaugh0EU4NQ5
|
||||
PoZxsLpB0gUsvNDGE0V5/2Q85GmsYzlBjBuoM+RfvF2fSP+dDTs3Hwjgo2YwZDAO
|
||||
BgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU95Au
|
||||
B82vrt2UJyDTNBQH3B8sePUwHwYDVR0jBBgwFoAUgwZucvb+H/1chTPLQ1GYTJwK
|
||||
CXQwCgYIKoZIzj0EAwIDRwAwRAIgSaHuI61rNsFf1ke5WSUyuqy51DIE/ONCSWKT
|
||||
VQgTVJMCIAMsE+Eibk43hL4qQi5vBJiFLfGQDDN/9HUi6w4w5EZ7
|
||||
-----END CERTIFICATE-----
|
25
ca/identity/testdata/identity/identity.crt
vendored
Normal file
25
ca/identity/testdata/identity/identity.crt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICHzCCAcagAwIBAgIQfVgJ4dZ2AhS88uthvlIzyjAKBggqhkjOPQQDAjAkMSIw
|
||||
IAYDVQQDExlTbWFsbHN0ZXAgSW50ZXJtZWRpYXRlIENBMB4XDTE5MTIxMjAyNDgy
|
||||
MVoXDTI5MTIwOTAyNDgyMVowGjEYMBYGA1UEAwwPam9lQGV4YW1wbGUuY29tMFkw
|
||||
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjT41KODf68aEB5kavE+SytcWqrQAhQEP
|
||||
edA+YY+5RYgSZu3qqncRUX+j4rDNaAO/l/MGYOUGR0FHP3FzdchxDaOB4zCB4DAO
|
||||
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0G
|
||||
A1UdDgQWBBTUe3rNfYx5VdyfGEziHFTREJuU2jAfBgNVHSMEGDAWgBT3kC4Hza+u
|
||||
3ZQnINM0FAfcHyx49TAaBgNVHREEEzARgQ9qb2VAZXhhbXBsZS5jb20wUwYMKwYB
|
||||
BAGCpGTGKEABBEMwQQIBAQQPam9lQGV4YW1wbGUuY29tBCsyd1NOX0NtZXhYV2ln
|
||||
X0RucFZac1lGZE1IMVN0Yzg2QklCek4wcnQ1aXBFMAoGCCqGSM49BAMCA0cAMEQC
|
||||
IHkYnKUBrXc/GIosKgnhHqVeRMi2O1JhnZdTE1uoy2C0AiA9ZrmGqPvpQ86f5yq5
|
||||
llsieqBTzIum6A45q0/4XeN3QA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBozCCAUqgAwIBAgIQF4UYp5uEiuq/BO0cOWTq9DAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
|
||||
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQGECLvDj+ZSqW78DRmUaugh0EU4NQ5
|
||||
PoZxsLpB0gUsvNDGE0V5/2Q85GmsYzlBjBuoM+RfvF2fSP+dDTs3Hwjgo2YwZDAO
|
||||
BgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU95Au
|
||||
B82vrt2UJyDTNBQH3B8sePUwHwYDVR0jBBgwFoAUgwZucvb+H/1chTPLQ1GYTJwK
|
||||
CXQwCgYIKoZIzj0EAwIDRwAwRAIgSaHuI61rNsFf1ke5WSUyuqy51DIE/ONCSWKT
|
||||
VQgTVJMCIAMsE+Eibk43hL4qQi5vBJiFLfGQDDN/9HUi6w4w5EZ7
|
||||
-----END CERTIFICATE-----
|
5
ca/identity/testdata/identity/identity_key
vendored
Normal file
5
ca/identity/testdata/identity/identity_key
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJ4A5QcJioS5I89uT/hkuWPy/nlW5qy8vM8Tm2sgUCDyoAoGCCqGSM49
|
||||
AwEHoUQDQgAEjT41KODf68aEB5kavE+SytcWqrQAhQEPedA+YY+5RYgSZu3qqncR
|
||||
UX+j4rDNaAO/l/MGYOUGR0FHP3FzdchxDQ==
|
||||
-----END EC PRIVATE KEY-----
|
25
ca/identity/testdata/identity/not_before.crt
vendored
Normal file
25
ca/identity/testdata/identity/not_before.crt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICIDCCAcagAwIBAgIQHRUI8eJv55I9/5IHi1mpmjAKBggqhkjOPQQDAjAkMSIw
|
||||
IAYDVQQDExlTbWFsbHN0ZXAgSW50ZXJtZWRpYXRlIENBMB4XDTI5MTIwOTAzMzAx
|
||||
NFoXDTI5MTIxMDAzMzAxNFowGjEYMBYGA1UEAwwPam9lQGV4YW1wbGUuY29tMFkw
|
||||
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjT41KODf68aEB5kavE+SytcWqrQAhQEP
|
||||
edA+YY+5RYgSZu3qqncRUX+j4rDNaAO/l/MGYOUGR0FHP3FzdchxDaOB4zCB4DAf
|
||||
BgNVHSMEGDAWgBT3kC4Hza+u3ZQnINM0FAfcHyx49TAOBgNVHQ8BAf8EBAMCBaAw
|
||||
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTUe3rNfYx5
|
||||
VdyfGEziHFTREJuU2jAaBgNVHREEEzARgQ9qb2VAZXhhbXBsZS5jb20wUwYMKwYB
|
||||
BAGCpGTGKEABBEMwQQIBAQQPam9lQGV4YW1wbGUuY29tBCsyd1NOX0NtZXhYV2ln
|
||||
X0RucFZac1lGZE1IMVN0Yzg2QklCek4wcnQ1aXBFMAoGCCqGSM49BAMCA0gAMEUC
|
||||
IQDJVzxQ0lY9+haZLs5qxhbaWoTmXwCbYdkwhThDfM/izwIgRZCmshc1flfimIPO
|
||||
eblT85Gk16ND/diV6pmtUaMT73I=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBozCCAUqgAwIBAgIQF4UYp5uEiuq/BO0cOWTq9DAKBggqhkjOPQQDAjAcMRow
|
||||
GAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTAeFw0xOTEyMTIwMjQ1MThaFw0yOTEy
|
||||
MDkwMjQ1MThaMCQxIjAgBgNVBAMTGVNtYWxsc3RlcCBJbnRlcm1lZGlhdGUgQ0Ew
|
||||
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQGECLvDj+ZSqW78DRmUaugh0EU4NQ5
|
||||
PoZxsLpB0gUsvNDGE0V5/2Q85GmsYzlBjBuoM+RfvF2fSP+dDTs3Hwjgo2YwZDAO
|
||||
BgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU95Au
|
||||
B82vrt2UJyDTNBQH3B8sePUwHwYDVR0jBBgwFoAUgwZucvb+H/1chTPLQ1GYTJwK
|
||||
CXQwCgYIKoZIzj0EAwIDRwAwRAIgSaHuI61rNsFf1ke5WSUyuqy51DIE/ONCSWKT
|
||||
VQgTVJMCIAMsE+Eibk43hL4qQi5vBJiFLfGQDDN/9HUi6w4w5EZ7
|
||||
-----END CERTIFICATE-----
|
8
ca/identity/testdata/secrets/intermediate_ca_key
vendored
Normal file
8
ca/identity/testdata/secrets/intermediate_ca_key
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,37e3019a1aa420225bbd4f342a3ce330
|
||||
|
||||
3SNIIXzE11cGKTPnErv8S1HIrd2lbQo+lsMT9GrU33GAi/MTvp0hx0txy7E3CsrU
|
||||
DbuPXs3zLCjgoNLOeyAWLqGjPLRt4YNnZGVDi3F/dFUAWxgXH8gZQ2d9ZqAXwxdd
|
||||
bhT4ZcRFgFzCPlHExtxBrJe+Tmeuq1HqD+8gpOSYbt0=
|
||||
-----END EC PRIVATE KEY-----
|
8
ca/identity/testdata/secrets/root_ca_key
vendored
Normal file
8
ca/identity/testdata/secrets/root_ca_key
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,48fc92ab6885b2377d8bbac5b035bde2
|
||||
|
||||
BE07EXlLmJbAfjt2c9GwQoTT07DzjLWgiGWqxMKC0bOLQdmHe2pFudeQldDhTOme
|
||||
xnr9rRj9h+GRWV+sIzp+ilGd4/F6lfzWMl44GA5y7uBNWKhnI1uB9m9oo69hBNRg
|
||||
dQuDmAx5EWXvg7Mgg1MQZIPY8539RXWJdAs+uRSI12g=
|
||||
-----END EC PRIVATE KEY-----
|
5
ca/identity/testdata/secrets/server_key
vendored
Normal file
5
ca/identity/testdata/secrets/server_key
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIIGgfuMfx7h1VaCYzzEPZhrbTLsAr6dtyuQ2RLl6jKqBoAoGCCqGSM49
|
||||
AwEHoUQDQgAE5kETAs0T9YQXGIQF5W4skfULbEKLEHwmU0vnp4Ok7S/VY1rEF6nd
|
||||
UkkrX4tIKz8ok0CyD4T20oaP1Sc0qX+fQw==
|
||||
-----END EC PRIVATE KEY-----
|
Loading…
Reference in a new issue