diff --git a/docs/connectivity/2-credentials/1-pki.md b/docs/connectivity/2-credentials/1-pki.md deleted file mode 100644 index f3d39f43..00000000 --- a/docs/connectivity/2-credentials/1-pki.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: Public Key Infrastructure ---- - -A robust [Public Key Infrastructure -(PKI)](https://en.wikipedia.org/wiki/Public_key_infrastructure) is imperative -for ensuring secure cloud communication throughout the lifecycle of devices in a -fleet. PKI includes the creation, management, and distribution of keys and -certificates used in public-key cryptography. - -A central tenet of public-key cryptography is the protection of private key -material. Establishing PKI allows for private keys to be generated in and never -leave secure storage on a device. This dramatically reduces the potential of -private key material being compromised. - -## Establishing PKI - -In order to start leveraging PKI for device certificates, it is necessary to -provision infrastructure and establish at least one certiciate authority (CA). - -### Setting Up Infrastructure - -Customers are in full control of their PKI when using Golioth. While it is -possible to establish your own infrastructure, doing so requires extreme care -and domain expertise. For most organizations, leveraging a PKI vendor is -recommended. - -For demonstration purposes, local PKI can be established using tools such as -[`openssl`](https://github.com/openssl/openssl) or -[`cfssl`](https://github.com/cloudflare/cfssl). - -### Establishing a Certificate Authority - -Device certificates are issued by a certificate authority (CA). A CA is -typically comprised of a _root CA certificate_, and one or more _intermediate CA -certificates_, which are signed by the root and used to sign device -certificates. - -To generate a root CA certificate using `openssl`, a private key must first be -generated. - -``` -openssl ecparam -name prime256v1 -genkey -noout -out "ca.key.pem" -``` - -Because the root CA certificate serves as the anchor in a chain of trust, it is -self-signed with the previously generated key. - -``` -openssl req -x509 -new -nodes \ - -key "ca.key.pem" \ - -sha256 -subj "/CN=Root CA" \ - -days 10 -out "ca.crt.pem" -``` - -In this example, the root CA certificate is being generated with a common name -of `Root CA` and an expiration in `10` days. In a production scenario, root CA -certificates typically have an expiration many years in the future in order to -minimize the churn of establishing a new chain of trust. - -### Integrating with Golioth - -In order for Golioth to establish a chain of trust with certificates presented -by devices connecting to the platform, the root CA certificate and any -intermediate CA certificates must be uploaded in the relevant Golioth project. -This allows Golioth to verify that the certificate presented by a devices was -signed using the configured CA. If the device is then able to prove possession -of the private key associated with their certificate, then you can be certain -that it is a valid device and should be allowed to communicate. - -CA certificates can be uploaded in a Golioth project by navigating to the -`Certificates` section under `Credentials`. - -## Generating Device Certificates - -In a production provisioning flow, a private key should never leave the secure -region on the device where it is generated and stored. Instead, a _certificate -signing request (CSR)_ should be generated and exported. Some devices -incorporate a dedicated secure element IC for this purpose, while others -leverage integrated secure storage. - -The CSR is signed by the device's private key and can be presented to a CA, -which can then issue a signed certificate that can then be returned to the -device. The signed certificate is only useful for a device that can prove -possession of the associated private key. If the private key never leaves the -secure region of the device, and the device has not been otherwise compromised, -then only it should be able to use the certificate to authenticate and establish -a secure communication channel with Golioth. - -:::note Device Certificate Requirements -Device certificates used with the Golioth platform must set the subject -organization (`O`) to the slug for the appropriate project, which can be found -under [`Project Settings`](https://console.golioth.io/project-settings). The -common name (`CN`) must be set to a unique identifier for the device within the -project. The unique value used in the common name is referred to as the device's -_certificate ID_. See the [Certificate IDs](#certificate-ids) section below for -more information. -::: - -For demonstration purposes, the previously created local CA can be used to -issue device certificates with `openssl`. The first step is generating a private -key for the device. - -``` -openssl ecparam -name prime256v1 -genkey -noout -out "device.key.pem" -``` - -The device private key can then be used to create a CSR. - -:::tip -Make sure to replace `PROJECT_SLUG` and `CERTIFICATE_ID` with appropriate -values for your Golioth project. -::: - -``` -openssl req -new \ - -key "device.key.pem" \ - -subj "/O=PROJECT_SLUG/CN=CERTIFICATE_ID" \ - -out "device.csr.pem" -``` - -Finally, the local CA can be used to issue a device certificate by signing the -certificate in the CSR. - -``` -openssl x509 -req \ - -in "device.csr.pem" \ - -CA "ca.crt.pem" \ - -CAkey "ca.key.pem" \ - -CAcreateserial \ - -out "device.crt.pem" \ - -days 7 -sha256 -``` - -The resulting device certificate (`device.crt.pem`) will have parameters that -match the supplied CSR, and an expiration of `7` days. Similarly to the root CA -certificate, device certificates should be created with an expiration that is -appropriate for the lifecycle of the device. - -:::tip -Keys and certificates may be encoded in different formats for distribution. The -`openssl` commands above produce text-based PEM (`.pem`) encoded files. Devices -will frequently use the more compact binary DER (`.der`) encoding. The following -commands can be used to convert PEM encoded keys and certificates to DER. -``` -openssl ec -in device.key.pem -outform DER -out device.key.der -``` -``` -openssl x509 -in device.crt.pem -outform DER -out device.crt.der -``` -::: - - -### Certificate IDs - -When issuing a device certificate, the certificate ID used in the common name -(`CN`) is a unique identifier within the Golioth project specified in the -organization (`O`) that is used to distinguish the physical device when using -the certificate. The sole purpose of this identifier is to associate the -physical device with a device on the Golioth platform. While a device's -certificate ID may match other device attributes, such as the device name, it -does not specifically connotate any other meaning. Using a dedicated identifier -for this purpose enables [zero-touch provisioning](#zero-touch-provisioning) and -other flexible provisioning workflows. - -When a physical device presents a valid certificate to Golioth and proves -possession of the associated private key, the physical device is associated with -a device on Golioth according to the following logic. - -1. If a Golioth device already exists with the given certificate ID, the - physical device is associated with it. -2. If a Golioth device exists with a name that matches the certificate ID, and - it has no certificate ID set, then the certificate ID is set and the physical - device is associated with it. -3. If no devices exist with either a matching certificate ID, or a matching name - and no certificate ID, then a new device is created on Golioth with the - certificate ID set, and the physical device is associated with it. - -After a certificate ID is set on a Golioth device it is immutable. However, the -name of the device remains mutable. In the third case above, this can lead to a -scenario where a Golioth device exists with a name and certificate ID, and the -name matches the certificate ID presented by the physical device, but the -certificate IDs do not match. If this occurs, a new Golioth device is created -with certificate ID set to match the physical device's certificate ID, and with -name set to the same value of the certificate ID with a random suffix appended. -Otherwise, the name of the newly created Golioth device will be set to the same -value of the certificate ID. - -## Verification of Golioth Server Certificate - -Similarly to how Golioth must be able to establish a chain of trust rooted in -the CA certificates uploaded in a project, a device must also be able to verify -that it is communicating with Golioth. To accomplish this, one or more root CA -certificates must be stored on the device. Golioth will present a server -certificate, or a chain of certificates, that allow the device to establish a -chain of trust rooted in the stored CA certificates. - -Firmware SDKs and libraries distributed by Golioth typically will include the -necessary root CA certificates to verify certificates presented by the platform. -For example, the [Golioth Firmware -SDK](https://github.com/golioth/golioth-firmware-sdk) embeds the ISRG Root X1 -and Golioth Root X1 root CA certificates, whereas the -[`pouch`](https://github.com/golioth/pouch) only embeds the latter. - -## Zero-Touch Provisioning - -The use of certificates enables devices to be created on the Golioth platform -without a user needing to interact with the console or [management -API](/reference/management-api). This workflow is referred to as _zero-touch -provisioning_ and can alleviate operational overhead, particularly when -deploying large fleets of devices. However, customers are still welcome to -manually provision devices prior to their first connection. diff --git a/docs/connectivity/2-credentials/1-pki/1-aws.md b/docs/connectivity/2-credentials/1-pki/1-aws.md new file mode 100644 index 00000000..60cd72e1 --- /dev/null +++ b/docs/connectivity/2-credentials/1-pki/1-aws.md @@ -0,0 +1,146 @@ +--- +title: "AWS Private CA" +--- + +To allow Golioth to use your AWS Private Certificate Authority service as a PKI +provider for your project, you need to go through a few steps in the AWS Console +before you can configure a connection from Golioth. + +For information about how you can establish a CA in AWS Private CA and issue +end-entity certificates, please refer to [the official AWS +documentation](https://docs.aws.amazon.com/privateca/latest/userguide/PcaWelcome.html). + +## Configuring AWS + +To allow Golioth to securely connect directly to your AWS Private CA service, +you'll need to create an IAM policy with the required permissions, then assign +that to a user. + +### 1. Create a policy + +Golioth requires a few permissions in the AWS Private CA service to be able to +authenticate devices and rotate certificates. + +As none of the default policies fit the permissions requirements exactly, we'll +start by creating a new policy specifically for the integration with Golioth. + +As an admin or an IAM user with the required permissions, navigate to the [IAM +Policy section](https://console.aws.amazon.com/iamv2/home#/policies), and click +**Create Policy**. Using the JSON Policy editor, add the following policy: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "acm-pca:ListCertificateAuthorities", + "acm-pca:GetCertificateAuthorityCertificate", + "acm-pca:GetCertificate" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "acm-pca:IssueCertificate" + ], + "Resource": "arn:aws:acm-pca:*:*:certificate-authority/*", + "Condition": { + "ArnLike": { + "acm-pca:TemplateArn": [ + "arn:aws:acm-pca:*:*:template/EndEntityClientAuthCertificate_APIPassthrough/V*" + ] + } + } + } + ] +} +``` + +The first statement in this policy enables Golioth to iterate through your +certificate authorities, and retrieve their certificates. The second statement +allows Golioth to issue device certificates using the +[`EndEntityClientAuthCertificate_APIPassthrough/V1` +template](https://docs.aws.amazon.com/privateca/latest/userguide/template-definitions.html#EndEntityClientAuthCertificate_APIPassthrough). + +:::tip +If you do not need certificate rotation capabilities, the +**AWSPrivateCAReadOnly** standard policy can be used instead. +::: + +Save this policy with a recognizable name and description. + +### 2. Create an IAM user + +Golioth connects to your AWS Private CA service as an IAM user. Although it's +possible for Golioth to authenticate as an existing user, we strongly recommend +establishing a dedicated user to maintain a narrow set of permissions. + +As an admin or an IAM user with the required permissions, navigate to the [IAM +User Management Dashboard](https://console.aws.amazon.com/iamv2/home#/users) in +the AWS Console, and click **Create User**. + +![Create a user](./assets/aws-user.png) + +Pick a recognizable user name, and click **Next** to go to the permissions +screen. + +### 3. Attach the policy to the user + +In the "Set Permissions" screen, select **Attach policies directly**, and search +for the policy created in [step 1](#1-create-a-policy). Select the policy, and +click **Next** to go the final user creation page. + +![Attaching the AWSPrivateCAReadOnly policy](./assets/aws-policy.png) + +Policies can either be attached to the user directly when you create it, or by +assigning the user to a user group with the required permissions. + +### 4. Create an access key + +Once the user is created with the required permissions, you'll need to create an +access key that Golioth can use to authenticate as that user. + +Follow [the AWS +documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-keys-admin-managed.html) +for instructions on how to create an access key for an IAM user. Note that the +secret access key is only available during the creation process, and must be +saved before leaving the page. + +## Connecting to AWS from the Golioth Console + +Once you have an AWS IAM user with the required permissions, you can configure +Golioth's connection to the AWS Private CA from the Golioth Console. Navigate to +the PKI Providers section in the sidebar, and click **Add Provider**. In the +modal window, select _AWS Private Certificate Authority_, and the correct region +for your AWS instance. Add the Access Key ID and Secret Access Key that you +created in the AWS Console, and click **Connect**. The provider will be added to +the list of known providers, and a provider status check will run. + +If everything is configured correctly, the provider status should change to +"Connected", and list the number of available certificate authorities. + +![Configured Provider](./assets/configured-provider.png) + +## Issuing Device Certificates + +Device certificates are [End Entity +Certificates](https://docs.aws.amazon.com/privateca/latest/userguide/PcaIssueCert.html) +in AWS. + +As outlined in the [Certificate ID section](./README.md#certificate-ids), +the device certificate subject needs to include the following attributes: + +- `Organization`: the device's project ID +- `CommonName`: a unique device certificate ID + +Other subject attributes are ignored. + +When performing certificate rotation, Golioth will submit certificate signing +requests to the AWS Private CA with the +[`EndEntityClientAuthCertificate_APIPassthrough/V1` +template](https://docs.aws.amazon.com/privateca/latest/userguide/template-definitions.html#EndEntityClientAuthCertificate_APIPassthrough). +The request will be submitted with an API passthrough value containing the +subject attributes above. diff --git a/docs/connectivity/2-credentials/1-pki/2-offline-pki.md b/docs/connectivity/2-credentials/1-pki/2-offline-pki.md new file mode 100644 index 00000000..889269d0 --- /dev/null +++ b/docs/connectivity/2-credentials/1-pki/2-offline-pki.md @@ -0,0 +1,136 @@ +--- +title: "Offline PKI" +--- + +If your Public Key Infrastructure is not supported as an integrated PKI provider, +you can manage your PKI offline, then upload your CA certificates to Golioth. For +production environments, establishing offline PKI using a secure PKI provider is +just as secure as using an integrated PKI provider, but it does not allow Golioth +to issue new device certificates on behalf of your devices. + +CA certificates can be uploaded to a Golioth project by navigating to the +`Certificates` section under `Credentials`. + +## Testing certificate based authentication with local PKI + +For demonstration and testing purposes, local PKI can be established using tools +such as [`openssl`](https://github.com/openssl/openssl) or +[`cfssl`](https://github.com/cloudflare/cfssl). + +:::warning +Building your PKI locally is not recommended for production environments, but +can be an easy way to get started with using certificate authentication. +::: + +### Establishing a Certificate Authority + +Device certificates are issued by a certificate authority (CA). A CA is +typically comprised of a _root CA certificate_, and one or more _intermediate CA +certificates_, which are signed by the root and used to sign device +certificates. + +To generate a root CA certificate using `openssl`, a private key must first be +generated. + +``` +openssl ecparam -name prime256v1 -genkey -noout -out "ca.key.pem" +``` + +Because the root CA certificate serves as the anchor in a chain of trust, it is +self-signed with the previously generated key. + +``` +openssl req -x509 -new -nodes \ + -key "ca.key.pem" \ + -sha256 -subj "/CN=Root CA" \ + -days 10 -out "ca.crt.pem" +``` + +In this example, the root CA certificate is being generated with a common name +of `Root CA` and an expiration in `10` days. In a production scenario, root CA +certificates typically have an expiration many years in the future in order to +minimize the churn of establishing a new chain of trust. + +### Integrating with Golioth + +Upload your CA certificates to your Golioth project by navigating to the +`Certificates` section under `Credentials`, then click **Add CA Certificate** and select your `ca.crt.pem` file. + +### Generating Device Certificates + +In a production provisioning flow, a private key should never leave the secure +region on the device where it is generated and stored. Instead, a _certificate +signing request (CSR)_ should be generated and exported. Some devices +incorporate a dedicated secure element IC for this purpose, while others +leverage integrated secure storage. + +The CSR is signed by the device's private key and can be presented to a CA, +which can then issue a signed certificate that can then be returned to the +device. The signed certificate is only useful for a device that can prove +possession of the associated private key. If the private key never leaves the +secure region of the device, and the device has not been otherwise compromised, +then only it should be able to use the certificate to authenticate and establish +a secure communication channel with Golioth. + +:::note Device Certificate Requirements +Device certificates used with the Golioth platform must set the subject +organization (`O`) to the slug for the appropriate project, which can be found +under [`Project Settings`](https://console.golioth.io/project-settings). The +common name (`CN`) must be set to a unique identifier for the device within the +project. The unique value used in the common name is referred to as the device's +_certificate ID_. See the [Certificate IDs](#certificate-ids) section below for +more information. +::: + +For demonstration purposes, the previously created local CA can be used to +issue device certificates with `openssl`. The first step is generating a private +key for the device. + +``` +openssl ecparam -name prime256v1 -genkey -noout -out "device.key.pem" +``` + +The device private key can then be used to create a CSR. + +:::tip +Make sure to replace `PROJECT_SLUG` and `CERTIFICATE_ID` with appropriate +values for your Golioth project. +::: + +``` +openssl req -new \ + -key "device.key.pem" \ + -subj "/O=PROJECT_SLUG/CN=CERTIFICATE_ID" \ + -out "device.csr.pem" +``` + +Finally, the local CA can be used to issue a device certificate by signing the +certificate in the CSR. + +``` +openssl x509 -req \ + -in "device.csr.pem" \ + -CA "ca.crt.pem" \ + -CAkey "ca.key.pem" \ + -CAcreateserial \ + -out "device.crt.pem" \ + -days 7 -sha256 +``` + +The resulting device certificate (`device.crt.pem`) will have parameters that +match the supplied CSR, and an expiration of `7` days. Similarly to the root CA +certificate, device certificates should be created with an expiration that is +appropriate for the lifecycle of the device. + +:::tip +Keys and certificates may be encoded in different formats for distribution. The +`openssl` commands above produce text-based PEM (`.pem`) encoded files. Devices +will frequently use the more compact binary DER (`.der`) encoding. The following +commands can be used to convert PEM encoded keys and certificates to DER. +``` +openssl ec -in device.key.pem -outform DER -out device.key.der +``` +``` +openssl x509 -in device.crt.pem -outform DER -out device.crt.der +``` +::: diff --git a/docs/connectivity/2-credentials/1-pki/README.md b/docs/connectivity/2-credentials/1-pki/README.md new file mode 100644 index 00000000..26e88647 --- /dev/null +++ b/docs/connectivity/2-credentials/1-pki/README.md @@ -0,0 +1,110 @@ +--- +title: Public Key Infrastructure +--- + +A robust [Public Key Infrastructure +(PKI)](https://en.wikipedia.org/wiki/Public_key_infrastructure) is imperative +for ensuring secure cloud communication throughout the lifecycle of devices in a +fleet. PKI includes the creation, management, and distribution of keys and +certificates used in public-key cryptography. + +A central tenet of public-key cryptography is the protection of private key +material. Establishing PKI allows for private keys to be generated in and never +leave secure storage on a device. This dramatically reduces the potential of +private key material being compromised. + +## Establishing PKI + +When one of your devices connects to Golioth, it'll prove its identity by +presenting a signed certificate. The device certificate contains the device's +public key, as well as its project and certificate ID. Device certificates are +issued by a _certificate authority_ (CA), which validated the information in the +certificate and signed it. + +The device certificate does not need to be registered ahead of time, and as +outlined in the [Zero-Touch Provisioning section](#zero-touch-provisioning) +below, the device will even be able to self-register when it first authenticates +with a valid certificate. + +To verify the certificate the device presented, Golioth goes through a list of +known CAs for your project. If the device's certificate was signed by one of the +known CAs, Golioth can trust the information within it, and the device can +start sending and receiving data. + +In order to start leveraging PKI for device certificates, it is necessary to +establish at least one CA, and register it with Golioth. + +### PKI Providers + +Golioth does not issue device certificates, and requires you to establish PKI +through an external service. + +Golioth can [integrate directly with the AWS Private Certificate Authority +service](./1-aws.md). Other PKI providers can be integrated into your project by +[establishing offline PKI, then uploading the CA certificates to +Golioth](./2-offline-pki.md). + +By integrating directly with an external PKI provider, Golioth automatically +keeps an up to date list of CAs, and is able to forward certificate signing +requests on behalf of your devices, allowing devices to perform certificate +rotation through Golioth's infrastructure. + +## Certificate IDs + +When issuing a device certificate, the certificate ID used in the common name +(`CN`) is a unique identifier within the Golioth project specified in the +organization (`O`) that is used to distinguish the physical device when using the +certificate. The sole purpose of this identifier is to associate the physical +device with a device on the Golioth platform. While a device's certificate ID may +match other device attributes, such as the device name, it does not specifically +connote any other meaning on the Golioth platform. Using a dedicated identifier +for this purpose enables [zero-touch provisioning](#zero-touch-provisioning) and +other flexible provisioning workflows. + +When a physical device presents a valid certificate to Golioth and proves +possession of the associated private key, the physical device is associated with +a device on Golioth according to the following logic. + +1. If a Golioth device already exists with the given certificate ID, the + physical device is associated with it. +2. If a Golioth device exists with a name that matches the certificate ID, and + it has no certificate ID set, then the certificate ID is set and the physical + device is associated with it. +3. If no devices exist with either a matching certificate ID, or a matching name + and no certificate ID, then a new device is created on Golioth with the + certificate ID set, and the physical device is associated with it. + +After a certificate ID is set on a Golioth device it is immutable. However, the +name of the device remains mutable. In the third case above, this can lead to a +scenario where a Golioth device exists with a name and certificate ID, and the +name matches the certificate ID presented by the physical device, but the +certificate IDs do not match. If this occurs, a new Golioth device is created +with certificate ID set to match the physical device's certificate ID, and with +name set to the same value of the certificate ID with a random suffix appended. +Otherwise, the name of the newly created Golioth device will be set to the same +value of the certificate ID. + +## Verification of Golioth Server Certificate + +Similarly to how Golioth must be able to establish a chain of trust rooted in +the CA certificates uploaded in a project, a device must also be able to verify +that it is communicating with Golioth. To accomplish this, one or more root CA +certificates must be stored on the device. Golioth will present a server +certificate, or a chain of certificates, that allow the device to establish a +chain of trust rooted in the stored CA certificates. + +Firmware SDKs and libraries distributed by Golioth typically will include the +necessary root CA certificates to verify certificates presented by the platform. +For example, the [Golioth Firmware +SDK](https://github.com/golioth/golioth-firmware-sdk) embeds the ISRG Root X1 +and Golioth Root X1 root CA certificates, whereas the +[`pouch`](https://github.com/golioth/pouch) only embeds the latter. + +## Zero-Touch Provisioning + +The use of certificates enables devices to be created on the Golioth platform +without a user needing to interact with the console or [management +API](/reference/management-api). This workflow is referred to as _zero-touch +provisioning_ and can alleviate operational overhead, particularly when +deploying large fleets of devices. However, customers are still welcome to +manually provision devices prior to their first connection. diff --git a/docs/connectivity/2-credentials/1-pki/_category_.yml b/docs/connectivity/2-credentials/1-pki/_category_.yml new file mode 100644 index 00000000..88dbaaed --- /dev/null +++ b/docs/connectivity/2-credentials/1-pki/_category_.yml @@ -0,0 +1,4 @@ +label: 'Public Key Infrastructure' +position: 1 # float position is supported +collapsible: true # make the category collapsible +collapsed: false # keep the category open by default diff --git a/docs/connectivity/2-credentials/1-pki/assets/aws-policy.png b/docs/connectivity/2-credentials/1-pki/assets/aws-policy.png new file mode 100644 index 00000000..a8f9242b Binary files /dev/null and b/docs/connectivity/2-credentials/1-pki/assets/aws-policy.png differ diff --git a/docs/connectivity/2-credentials/1-pki/assets/aws-user.png b/docs/connectivity/2-credentials/1-pki/assets/aws-user.png new file mode 100644 index 00000000..cef04706 Binary files /dev/null and b/docs/connectivity/2-credentials/1-pki/assets/aws-user.png differ diff --git a/docs/connectivity/2-credentials/1-pki/assets/configured-provider.png b/docs/connectivity/2-credentials/1-pki/assets/configured-provider.png new file mode 100644 index 00000000..56e9b7b1 Binary files /dev/null and b/docs/connectivity/2-credentials/1-pki/assets/configured-provider.png differ