# 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
- Getting Started
- API Documentation
- Identity and Certificate Authorities
- Configuration Files
- Examples
- About This Project
- References
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
- Begin by installing the repository dependencies using the following command:
go install github.com/scorpio-id/pki@latest
-
Set up a configuration file and update its location within
main.go
-
Start the application by running the following command:
go run ./cmd/main.go
- 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
Key | Description | Type | Example |
---|---|---|---|
host | The host/domain of the application. | String | "http://127.0.0.1" |
port | Which port this application binds to. | Integer | 8081 |
pki
Key | Description | Type | Example |
---|---|---|---|
rsa_bits | Number of bits within key. | Integer | 2048 |
serial_number | Integer | 1000 | |
csr_max_memory | Max number of bits that will be allocated for a request. | Integer | 1024 |
certificate_ttl | Time a certificate is valid until once issued. | String | "60m" |
certificate_authority | Identity information of this service. For more information about possible headers go here | Nested KV | common_name: "scorpio.io" |
allowed_name | Regular Expressions which will be used to match appropiate SANs | List | - "^$" ".\.scorpio\.io" ".\.example\.com" |
oauth
Key | Description | Type | Example |
---|---|---|---|
enabled | Whether OAuth is required to be used. | Boolean | True |
trusted_issuers | Domains 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