Categorygithub.com/scorpio-id/pki
module
0.1.0
Repository: https://github.com/scorpio-id/pki.git
Documentation: pkg.go.dev

# README

PKI

Scorpio ID's PKI service is a configurable X.509 Certificate Authority implemented in Go with native support to handle CSRs and PKCS #12 secured with OAuth2.

Once configured, a running instance exposes a series of endpoints in which a client or service may request a valid X.509 certificate issued by this CA.

Contents

What is PKI

Public Key Infrastructure (PKI) facilitates the creation and distribution of digital certificates. This service serves as the foundation for modern HTTPS, and enables communication between services on the web. More information can be found in the official RFC: RFC 5280.

Getting Started

  1. Begin by installing the repository dependencies using the following command:
go install github.com/scorpio-id/pki@latest
  1. Set up a configuration file and update its location within main.go

  2. Start the application by running the following command:

go run ./cmd/main.go
  1. Verify that the instance is running by checking the corresponding swagger page: hostDomain:port/swagger/index.html

Submit a CSR

A client must be able to send a multipart/form-data HTTPS request to the /certificate endpoint with a key-value pair "csr" containing a valid PEM-encoded CSR.

An example of this POST request in cURL can be seen below assuming OAuth is enabled:

curl \
--location 'localhost:8081/certificate' \
--header 'Authorization: Bearer <valid-jwt-here>' \
--form 'csr="<valid-pem-encoded-csr-here>"'

A Go implementation of this request can be found below.

Steps on how to generate these can be found below:

Request a PKCS #12

Similarly to a CSR, clients must be able to send application/x-www-form-urlencoded data to the /p12 endpoint with "san" form parameters set to qualifying domain names.

curl \
--location 'localhost:8081/p12' \
--header 'Authorization: Bearer <valid-jwt-here>' \
-d "san=example1.com&san=example2.com"

API Documentation

Running this application initiates a swagger page on the /swagger endpoint where REST API documentation can be found describing each endpoint and supported operations. Additional example requests are provided within the documentation.

Identity and Certificate Authorities

Both CAs and clients are entities that require certain information to be provided between both parties for proper servicing.

Scorpio ID's CA Identity

A RSA key pair is generated at runtime and the corresponding PEM-encoded public key is accessible at the /public endpoint. This is the primary identifier used to verify that a certificate was signed by this CA instance.

This CA's information is integrated within all certificates signed and generated by the service instance. Further information can be expanded upon within the configuration file.

The Common Name header is required to be defined here.

Other optional headers:

  • Organization
  • Country
  • Locality
  • Province
  • Intermediate

Configuration Files

The configuration files for this project can be found in ./internal/config.

Each .yaml file requires the following headers:

server

KeyDescriptionTypeExample
hostThe host/domain of the application.String"http://127.0.0.1"
portWhich port this application binds to.Integer8081

pki

KeyDescriptionTypeExample
rsa_bitsNumber of bits within key.Integer2048
serial_numberInteger1000
csr_max_memoryMax number of bits that will be allocated for a request.Integer1024
certificate_ttlTime a certificate is valid until once issued.String"60m"
certificate_authorityIdentity information of this service. For more information about possible headers go hereNested KVcommon_name: "scorpio.io"
allowed_nameRegular Expressions which will be used to match appropiate SANsList- "^$"
".\.scorpio\.io"
".
\.example\.com"

oauth

KeyDescriptionTypeExample
enabledWhether OAuth is required to be used.BooleanTrue
trusted_issuersDomains which the host can do OAuth with.List-"http://localhost:8082/jwks"
"https://scorpio.io/jwks"

Examples

Sending a Certificate Signing Request in Go

import (
  "fmt"
  "bytes"
  "mime/multipart"
  "net/http"
  "io/ioutil"
)

func main() {

  url := "localhost:8081/certificate"
  method := "POST"
  csr := "-----BEGIN NEW CERTIFICATE REQUEST-----\n<GOES HERE>\N----END NEW CERTIFICATE REQUEST-----"
  token := "<valid OAuth2 Token issued from trusted_issuers in config>"

  payload := &bytes.Buffer{}
  writer := multipart.NewWriter(payload)

  _ = writer.WriteField("csr", csr)
  err := writer.Close()
  if err != nil {
    fmt.Println(err)
    return
  }


  client := &http.Client {}
  req, err := http.NewRequest(method, url, payload)
  if err != nil {
    fmt.Println(err)
    return
  }

  req.Header.Add("Authorization", "Bearer "+ token)
  req.Header.Set("Content-Type", writer.FormDataContentType())

  res, err := client.Do(req)
  if err != nil {
    fmt.Println(err)
    return
  }

  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    fmt.Println(err)
    return
  }

  fmt.Println(string(body))
}

About This Project

This project was made to make integrating a Certificate Authority in Go much, much easier!

References and Resources

RFC 5280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

Useful Links

X.509 Encodings and Conversions - Information on encoding PEM, DER, CRT, and CER

# Packages

No description provided by the author
Package docs Code generated by swaggo/swag.
No description provided by the author