forked from globalsign/est
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e5339f7
Showing
62 changed files
with
10,921 additions
and
0 deletions.
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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Temporary files | ||
*.out | ||
*.swp | ||
*~ | ||
|
||
# Log files | ||
*.log | ||
|
||
# Executable files | ||
cmd/estserver/estserver | ||
cmd/estclient/estclient |
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,6 @@ | ||
# Changelog | ||
|
||
## [1.0.0] - 2020-05-28 | ||
|
||
### Added | ||
- Initial release |
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,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 GMO GlobalSign, Inc. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
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,116 @@ | ||
# est | ||
|
||
[![GoDoc](https://godoc.org/github.com/globalsign/est?status.svg)](https://godoc.org/github.com/globalsign/est) | ||
|
||
An implementation of the Enrollment over Secure Transport (EST) certificate | ||
enrollment protocol as defined by [RFC7030](https://tools.ietf.org/html/rfc7030). | ||
|
||
The implementation provides: | ||
|
||
* An EST client library; | ||
* An EST client command line utility using the client library; and | ||
* An EST server which can be used for testing and development purposes. | ||
|
||
The implementation is intended to be mostly feature-complete, including | ||
support for: | ||
|
||
* The optional `/csrattrs` and `/serverkeygen` operations, with support for | ||
server-generated private keys returned with or without additional | ||
encryption | ||
* The optional additional path segment | ||
* Optional HTTP-based client authentication on top of certificate-based | ||
TLS authentication | ||
|
||
In addition, a non-standard operation is implemented enabling EST-like | ||
enrollment using the privacy preserving protocol for distributing credentials | ||
for keys on a Trusted Platform Module (TPM) 2.0 device, as described in Part 1, | ||
section 24 of the Trusted Platform Module 2.0 Library specification. | ||
|
||
## Installation | ||
|
||
go get -u github.com/globalsign/est | ||
go install github.com/globalsign/est/cmd/estserver | ||
go install github.com/globalsign/est/cmd/estclient | ||
|
||
## Quickstart | ||
|
||
### Starting the server | ||
|
||
When started with no configuration file, the EST server listens on | ||
localhost:8443 and generates a random, transient Certificate Authority (CA) | ||
which can be used for testing: | ||
|
||
user@host:$ estserver & | ||
[1] 62405 | ||
|
||
Refer to the documentation for more details on using a configuration file. | ||
|
||
### Getting the CA certificates | ||
|
||
Because we're using a random, transient CA, we must retrieve the CA certificates | ||
in insecure mode to establish an explicit trust anchor for subsequent EST | ||
operations. Since we only need the root CA certificate to establish a trust | ||
anchor, we use the `-rootout` flag: | ||
|
||
user@host:$ estclient cacerts -server localhost:8443 -insecure -rootout -out anchor.pem | ||
|
||
We will also obtain and store the full CA certificates chain, since we'll use | ||
it shortly to demonstrate reenrollment. Since we now have an explicit trust | ||
anchor, we can use it instead of the `-insecure` option. Since we're storing | ||
the full chain, we don't use the `-rootout` option here: | ||
|
||
user@host:$ estclient cacerts -server localhost:8443 -explicit anchor.pem -out cacerts.pem | ||
|
||
### Enrolling with an existing private key | ||
|
||
First we generate a new private key, here using openssl: | ||
|
||
user@host:$ openssl genrsa 4096 > key.pem | ||
Generating RSA private key, 4096 bit long modulus | ||
.................+++ | ||
.............+++ | ||
e is 65537 (0x10001) | ||
|
||
Then we generate a PKCS#10 certificate signing request, and enroll using the | ||
explicit trust anchor we previously obtained: | ||
|
||
user@host:$ estclient csr -key key.pem -cn 'John Doe' -emails '[email protected]' -out csr.pem | ||
user@host:$ estclient enroll -server localhost:8443 -explicit anchor.pem -csr csr.pem -out cert.pem | ||
|
||
Using a configuration file, we can enroll with a private key resident on a | ||
hardware module, such as a hardware security module (HSM) or a Trusted Platform | ||
Module 2.0 (TPM) device. Refer to the documentation for more details. | ||
|
||
### Enrolling with a server-generated private key | ||
|
||
If we're unable or unwilling to create our own private key, the EST server can | ||
generate one for us, and return it along with our certificate: | ||
|
||
user@host:$ estclient serverkeygen -server localhost:8443 -explicit anchor.pem -cn 'Jane Doe' -out cert.pem -keyout key.pem | ||
|
||
Note that we can omit the `-csr` option when enrolling and the EST client can | ||
dynamically generate a CSR for us using fields passed at the command line and | ||
the private key we specified, or an automatically-generated ephemeral private | ||
key if we are requesting server-side private key generation. | ||
|
||
### Reenrolling | ||
|
||
Whichever way we generated our private key, we can now use it to reenroll. | ||
|
||
To reenroll a previously obtained certificate, we must use it to authenticate | ||
ourselves during the TLS handshake with the EST server. Since our random, | ||
transient CA uses an intermediate CA certificate, we must provide a chain of | ||
certificates to the EST client, or the TLS handshake may fail. | ||
|
||
Although providing the root CA certificate is optional for a TLS handshake, | ||
the simplest option is to provide the certificate we received along with the | ||
full chain of CA certificates which we previously obtained. To do this, we | ||
can just append those CA certificates to the certificate we received, and | ||
use that chain to reenroll: | ||
|
||
user@host:$ cat cert.pem cacerts.pem >> certs.pem | ||
user@host:$ estclient reenroll -server localhost:8443 -explicit anchor.pem -key key.pem -certs certs.pem -out newcert.pem | ||
|
||
Note that when we omit the `-csr` option when reenrolling, the EST client | ||
automatically generates a CSR for us by copying the subject field and subject | ||
alternative name extension from the certificate we're renewing. |
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,82 @@ | ||
/* | ||
Copyright (c) 2020 GMO GlobalSign, Inc. | ||
Licensed under the MIT License (the "License"); you may not use this file except | ||
in compliance with the License. You may obtain a copy of the License at | ||
https://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package est | ||
|
||
import ( | ||
"context" | ||
"crypto/x509" | ||
"net/http" | ||
) | ||
|
||
// CA is a Certificate Authority backing an EST server. The server can be | ||
// connected to any backing CA by providing an implementation of this interface. | ||
// | ||
// All operations receive: | ||
// - a context, from which the EST server logger can be retrieved by calling | ||
// LoggerFromContext | ||
// - the optional URI additional path segment (RFC7030 3.2.2) | ||
// - the HTTP request object from the server, from which the HTTP headers | ||
// passed by the client (including the Host header, to support virtual | ||
// servers) can be obtained | ||
// | ||
// Any error object returned from these functions which implements Error will be | ||
// used by the EST server to determine the HTTP response code, human-readable | ||
// error description, and Retry-After header value, if applicable. Any other | ||
// error will be treated as an internal server error. | ||
type CA interface { | ||
// CACerts requests a copy of the current CA certificates. See RFC7030 4.1. | ||
CACerts(ctx context.Context, aps string, r *http.Request) ([]*x509.Certificate, error) | ||
|
||
// CSRAttrs requests a list of CA-desired CSR attributes. The returned list | ||
// may be empty. See RFC7030 4.5. | ||
CSRAttrs(ctx context.Context, aps string, r *http.Request) (CSRAttrs, error) | ||
|
||
// Enroll requests a new certificate. See RFC7030 4.2. | ||
Enroll(ctx context.Context, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, error) | ||
|
||
// Reenroll requests renewal/rekey of an existing certificate. See RFC7030 | ||
// 4.2. | ||
Reenroll(ctx context.Context, cert *x509.Certificate, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, error) | ||
|
||
// ServerKeyGen requests a new certificate and a private key. The key must | ||
// be returned as a DER-encoded PKCS8 PrivateKeyInfo structure if additional | ||
// encryption is not being employed, or returned inside a CMS SignedData | ||
// structure which itself is inside a CMS EnvelopedData structure. See | ||
// RFC7030 4.4. | ||
ServerKeyGen(ctx context.Context, csr *x509.CertificateRequest, aps string, r *http.Request) (*x509.Certificate, []byte, error) | ||
|
||
// TPMEnroll requests a new certificate using the TPM 2.0 privacy-preserving | ||
// protocol. An EK certificate chain with a length of at least one must be | ||
// provided, along with the EK and AK public areas. The return values are an | ||
// encrypted credential blob, an encrypted seed, and the certificate itself | ||
// inside a CMS EnvelopedData encrypted with the credential as a pre-shared | ||
// key. | ||
TPMEnroll(ctx context.Context, csr *x509.CertificateRequest, ekcerts []*x509.Certificate, ekPub, akPub []byte, aps string, r *http.Request) ([]byte, []byte, []byte, error) | ||
} | ||
|
||
// Error represents an error which can be translated into an HTTP | ||
// status code and message, and optionally specify a Retry-After period. | ||
type Error interface { | ||
// StatusCode returns the HTTP status code. | ||
StatusCode() int | ||
|
||
// Error returns a human-readable description of the error. | ||
Error() string | ||
|
||
// RetryAfter returns the value in seconds after which the client should | ||
// retry the request. | ||
RetryAfter() int | ||
} |
Oops, something went wrong.