Skip to content

jjrdk/opencertserver

Repository files navigation

Introduction

About

OpenCertServer is a certificate server based on the Enrollment over Secure Transport profile (RFC 7030).

This profile, called Enrollment over Secure Transport (EST), describes a simple, yet functional, certificate management protocol targeting Public Key Infrastructure (PKI) clients that need to acquire client certificates and associated Certification Authority (CA) certificates. It also supports client-generated public/private key pairs as well as key pairs generated by the CA.

The project has been expanded to include support for the ACME protocol (RFC 8555) based on the following projects:

The projects have been migrated because they have not been updated in a long time, so to reduce the risk of being able to make the necessary API changes.

License

The project is licensed under the MIT license.

Both integrated projects are MIT licensed and the license terms remain the same.

Encryption over Secure Transport (EST)

Setup

In order to add the endpoints defined in the EST profile, you need to add the necessary services and configure your web application as described below.

The exact configuration of the authentication and authorization will depend on your local authorization rules.

The EST profile requires certificate authentication, and must be configured as an authentication scheme.

Configuration Values for Servers

The certificate server can be customized by setting the environment variables defined below. In addition to the application specific variables below, the standard ASP.NET environments can also be passed.

Note that some environment variables use double underscore __. This is to ensure compatibility with the .NET conversion from environment variable to hierarchical configuration value.

Environment Variable Type Description
RSA_PEM string (optional) Sets the path to the CA RSA certificate in PEM format. If the value is missing the application cannot start.
RSA_KEY string (optional) Set the path to the CA RSA key file.
ECDSA_PEM string (optional) Sets the path to the CA ECDSA certificate in PEM format. If the value is missing the application cannot start.
ECDSA_KEY string (optional) Set the path to the CA RSA key file.
WEB_PEM string (optional) Sets the path to the PEM certificate to use to secure the web server.
WEB_KEY string (optional) Set the path to the web server's PEM key.

Service collection configuration:

public IServiceCollection ConfigureServices(IServiceCollection sc)
{
    sc.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme);
    sc.ConfigureOptions<ConfigureCertificateAuthenticationOptions>();
    sc.AddEstServer(rsaPrivate, ecdsaPrivate);
}

In the example above rsaPrivate and ecdsaPrivate are certificate authority root certificates, for handling certificate requests for RSA and ECDSA algorithms, respectively.

Application configuration

public void Configure(IApplicationBuilder app)
{
    app.UseEstServer();
}

The application builder configuration internally registers: CertificateForwarding, Routing, Authentication, Authorization and Endpoints, in that order.

You can also have a look at the tests to see an example setup.

Usage

When the server is configured, the following 3 endpoints are available:

/.well-known/est/cacerts (GET): This endpoint provides the server public key certificates.

/.well-known/est/simpleenroll (POST): This endpoint allows a user to enroll and receive a certificate based on a certificate request.

/.well-known/est/simplereenroll (POST): This endpoint provides a renewed certificate based on the provides client certificate. This endpoint requires a client certificate which will be used both to authenticate and to process the renewal request.

Automatic Certificate Management Environment (ACME)

Configure the services

Add the following code to your Startup class' ConfigureServices method with real values instead of the sample values:

Note that you can set either TimeUntilExpiryBeforeRenewal, TimeAfterIssueDateBeforeRenewal or both, but at least one of them has to be specified.

//the following line adds the automatic renewal service.
services.AddAcmeClient(new LetsEncryptOptions() // see below
{
	Email = "[email protected]", //LetsEncrypt will send you an e-mail here when the certificate is about to expire
	UseStaging = false, //switch to true for testing
	Domains = new[] { DomainToUse },
	TimeUntilExpiryBeforeRenewal = TimeSpan.FromDays(30), //renew automatically 30 days before expiry
	TimeAfterIssueDateBeforeRenewal = TimeSpan.FromDays(7), //renew automatically 7 days after the last certificate was issued
	CertificateSigningRequest = new CsrInfo() //these are your certificate details
	{
		CountryName = "Denmark",
		Locality = "DK",
		Organization = "Fluffy Spoon",
		OrganizationUnit = "Hat department",
		State = "DK"
	}
});

The `LetEncryptOptions` sealed class is a sub-class of `AcmeOptions` which is configured to use the LetsEncrypt endpoints. To use a custom ACME server, create your own options sealed class which inherits from `AcmeOptions`.

//the following line tells the library to persist the certificate to a file, so that if the server restarts, the certificate can be re-used without generating a new one.
services.AddAcmeFileCertificatePersistence();

//the following line tells the library to persist challenges in-memory. challenges are the "/.well-known" URL codes that LetsEncrypt will call.
services.AddAcmeMemoryChallengePersistence();

Inject the middleware

Inject the middleware in the Startup class' Configure method as such:

public void Configure()
{
	app.UseAcmeClient();
}

Set default bindings

Call UseUrls with http://* and https://* in Program.cs

 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseUrls(new string[] { "http://*", "https://*" });
                    webBuilder.UseStartup<Startup>();
                });

Your application now supports SSL via LetsEncrypt, even from the first HTTPS request. It will even renew your certificate automatically in the background.

Optional: Configuring persistence

Persistence tells the middleware how to persist and retrieve the certificate, so that if the server restarts, the certificate can be re-used without generating a new one.

A certificate has a key to distinguish between certificates, since there is both an account certificate and a site certificate that needs to be stored.

File persistence

services.AddAcmeFileCertificatePersistence();
services.AddAcmeFileChallengePersistence();

Custom persistence

services.AddAcmeCertificatePersistence(/* your own ILetsEncryptPersistence implementation */);
services.AddAcmeChallengePersistence(/* your own ILetsEncryptPersistence implementation */);

//you can also customize persistence via delegates.
services.AddAcmeCertificatePersistence(
	async (key, bytes) => File.WriteAllBytes("certificate_" + key, bytes),
	async (key) => File.ReadAllBytes("certificate_" + key, bytes));

//the same can be done for challenges, with different arguments.
services.AddAcmeChallengePersistence(
	async (challenges) => ... /* Do something to serialize the collection of challenges and store it */,
	async () => ... /* Retrieve the stored collection of challenges */,
	async (challenges) => ... /* Delete the specified challenges */);

Building the Project

To build the project, run the build script (build.ps1 on Windows, build.sh on Linux/Mac). This will generate a set of nuget packages which can be used to integrate OpenCertServer into an ASP.NET Core server project.

Reporting Issues and Bugs

When reporting issues and bugs, please provide a clear set of steps to reproduce the issue. The best way is to provide a failing test case as a pull request.

If that is not possible, please provide a set of steps which allow the bug to be reliably reproduced. These steps must also reproduce the issue on a computer that is not your own.

Contributions

All contributions are appreciated. Please provide them as an issue with an accompanying pull request.

This is an open source project. Please respect the license terms and the fact that issues and contributions may not be handled as fast as you may wish. The best way to get your contribution adopted is to make it easy to pull into the code base.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages