Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Certificate management #695

Merged
merged 41 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
119f1d5
Added some missing descriptions
jeremypoulter Jun 14, 2023
09d05cd
Initial tempate of the certificate manager
jeremypoulter Jul 2, 2023
dc41567
Fleshed out the API for the certificates
jeremypoulter Jul 15, 2023
34ee1fe
Redact private keys from the web API
jeremypoulter Jul 15, 2023
9c225e9
Added parsing of the certificates and keys
jeremypoulter Jul 15, 2023
081495f
Fixed erasing a certificate
jeremypoulter Jul 15, 2023
6b5340e
Added using the root certificates added to the certificate manager.
jeremypoulter Jul 16, 2023
26865c4
Retrieve the root CAs, mainly for testing
jeremypoulter Jul 17, 2023
51bdd5d
Ignore any certificates
jeremypoulter Jul 17, 2023
c13b707
Added saving and loading certificates to flash
jeremypoulter Jul 21, 2023
e58a80e
Added support for HTTPS server
jeremypoulter Jul 23, 2023
a77f116
Temp commit of WIP updates
jeremypoulter Jul 23, 2023
fbf689c
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter Jul 27, 2023
29150ed
Initial attempt to enable MQTT client certificates
jeremypoulter Aug 11, 2023
7f35463
Improved error handling and reporting for connection errors when conn…
jeremypoulter Aug 12, 2023
3fe084f
Lint fixes
jeremypoulter Aug 12, 2023
bb3a067
Added a note with the policy needed to allow OpenEVSE to work with AW…
jeremypoulter Aug 16, 2023
affa0bd
Disable the debug
jeremypoulter Aug 16, 2023
33bf7df
Whitespace fixes
jeremypoulter Aug 18, 2023
4be91b9
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter Sep 13, 2023
b97c01e
Use published library
jeremypoulter Oct 4, 2023
5e1167a
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter Nov 16, 2023
4f1cee4
Merge branch 'master' into jeremypoulter/issue29
jeremypoulter May 17, 2024
d88d4e2
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter May 17, 2024
4f84047
Merged GUI
jeremypoulter May 17, 2024
9bc1884
Update of pre-built GUI files
jeremypoulter May 17, 2024
e474ead
Updated the ID to be a string containing HEX
jeremypoulter May 23, 2024
960144a
Updated GUI
jeremypoulter May 24, 2024
f45c41d
Printing out the certificates can trigger the watchdog so commenting out
jeremypoulter May 24, 2024
1b984b8
Adding the Amazon Root CA
jeremypoulter May 24, 2024
1c28fc7
Bump to latest ESP32 platform
jeremypoulter May 24, 2024
5678366
Update of pre-built GUI files
jeremypoulter May 24, 2024
69dcfa9
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter Jun 3, 2024
6d4ab27
Don't build `elecrow_esp32_hmi_dev`
jeremypoulter Jun 3, 2024
ff023b5
Print the Git status
jeremypoulter Jun 3, 2024
c84b828
Fix GUI build
jeremypoulter Jun 3, 2024
3c22f70
Merge branch 'master' of github.com:OpenEVSE/ESP32_WiFi_V3.x into jer…
jeremypoulter Jun 3, 2024
59ae640
Merge branch 'master' into jeremypoulter/issue29
jeremypoulter Jul 6, 2024
7d7c3b5
Update of pre-built GUI files
jeremypoulter Jul 6, 2024
2859130
Merge branch 'master' into jeremypoulter/issue29
jeremypoulter Aug 7, 2024
db87203
Update of pre-built GUI files
jeremypoulter Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
- wt32-eth01
- esp32-c3-devkitc-02
- elecrow_esp32_hmi
- elecrow_esp32_hmi_dev
# - elecrow_esp32_hmi_dev
- openevse_wifi_tft_v1
- openevse_wifi_tft_v1_dev

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/build_gui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ jobs:
rm -f src/web_static/*.h

- name: Run PlatformIO
run:
run: |
pio run
git status

- name: Push any changed files
uses: stefanzweifel/git-auto-commit-action@v5
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,17 @@ lib/ESPAL
lib/MicroDebug
lib/StreamSpy
lib/MicroTasks
lib/jeremypoulter/ArduinoMongoose
lib/jeremypoulter/ConfigJson
lib/jeremypoulter/OpenEVSE
lib/jeremypoulter/ESPAL
lib/jeremypoulter/Micro Debug
lib/jeremypoulter/StreamSpy
lib/jeremypoulter/MicroTasks

*.bin
divert_sim/epoxyfsdata
divert_sim/epoxyeepromdata

*.pem
*.pem
111 changes: 110 additions & 1 deletion api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ paths:
$ref: ./models/Config.yaml
examples: {}
post:
description: |
Update the EVSE configuration
operationId: updateConfig
responses:
'200':
Expand Down Expand Up @@ -233,6 +235,8 @@ paths:
summary: Get the Manual Override status
description: Returns the current state of the manual override.
post:
description: |
Set the manual override
requestBody:
content:
application/json:
Expand Down Expand Up @@ -279,6 +283,9 @@ paths:
summary: Clear the manual override
/claims:
get:
description: |
List all claims made by EVSE clients.
The response will be an array of EVSE claims.
responses:
'200':
description: OK
Expand All @@ -294,6 +301,9 @@ paths:
summary: List EVSE claims
'/claims/{client}':
get:
description: |
Get the claim information for a specific client.
The response will be an EVSE claim.
responses:
'200':
description: OK
Expand Down Expand Up @@ -431,6 +441,9 @@ paths:
description: Numeric ID of the event
get:
summary: Get event details
description: |
This will get the details of a specific event in the schedule.
The response will be the EVSE state to set for that event.
responses:
'200':
description: OK
Expand All @@ -442,6 +455,8 @@ paths:
tags:
- Schedule
post:
description: |
Update the details of a specific event in the schedule.
responses:
'200':
$ref: '#/components/responses/UpdateSuccessful'
Expand All @@ -456,6 +471,8 @@ paths:
- Schedule
summary: Update event details
delete:
description: |
Remove a specific event from the schedule.
responses:
'200':
description: OK
Expand Down Expand Up @@ -523,7 +540,9 @@ paths:
'404':
$ref: '#/components/responses/NotFound'
operationId: getEventBlock
description: ''
description: |
Retrieve the log events for a specific block.
The block index range is returned by the /logs endpoint.
parameters:
- schema:
type: integer
Expand Down Expand Up @@ -817,6 +836,95 @@ paths:
$ref: '#/components/responses/BadRequest'
operationId: post-time
description: Set the time and associated config options. If not setting the time the `/config` endpoint can be used.
/certificates:
get:
summary: Get a list of certificates
description: |
Returns a list of certificates that have been uploaded to the OpenEVSE. The certificates are used to
authenticate the OpenEVSE to the MQTT broker, provide a secure web interface or as additional root CA
certificates.
operationId: listCertificates
tags:
- Certificates
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
certificates:
type: array
items:
$ref: './models/Certificate.yaml'
post:
summary: Upload a certificate
description: |
Upload a certificate to the OpenEVSE. The certificate can be used to authenticate the OpenEVSE to the MQTT
broker, provide a secure web interface or as additional root CA certificates.
operationId: uploadCertificate
tags:
- Certificates
requestBody:
content:
application/json:
schema:
$ref: './models/Certificate.yaml'
responses:
'200':
$ref: '#/components/responses/UpdateSuccessful'
'400':
$ref: '#/components/responses/BadRequest'
'/certificates/{id}':
get:
summary: Get a certificate
description: |
Returns a certificate that has been uploaded to the OpenEVSE. The certificate is used to
authenticate the OpenEVSE to the MQTT broker, provide a secure web interface or as additional root CA
certificates.
operationId: getCertificate
tags:
- Certificates
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: './models/Certificate.yaml'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
delete:
summary: Delete a certificate
description: |
Delete a certificate that has been uploaded to the OpenEVSE. The certificate is used to
authenticate the OpenEVSE to the MQTT broker, provide a secure web interface or as additional root CA
certificates.
operationId: deleteCertificate
tags:
- Certificates
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
$ref: '#/components/responses/UpdateSuccessful'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
components:
schemas:
Message:
Expand Down Expand Up @@ -963,3 +1071,4 @@ tags:
- name: Energy Meter
- name: Time
- name: Restart
- name: Certificates
68 changes: 50 additions & 18 deletions docs/mqtt.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### MQTT
# MQTT

MQTT and MQTTS (secure) connections are supported for status and control.

Expand All @@ -20,46 +20,45 @@ When the device disconnects from MQTT the same message is posted with `state":"d

All subsequent MQTT status updates will by default be be posted to `openevse-xxxx` where `xxxx` is the last 4 characters of the device ID. This base-topic can be changed via the MQTT service page.

#### OpenEVSE Status via MQTT
## OpenEVSE Status via MQTT

OpenEVSE can post its status values (e.g. amp, wh, temp1, temp2, temp3, pilot, status) to an MQTT server. Data will be published as a sub-topic of base topic, e.g `<base-topic>/amp`. Data is published to MQTT every 30s.

**The default `<base-topic>` is `openevse-xxxx` where `xxxx` is the last 4 characters of the device ID**

Claims & manual override are read accessible here:
`<base-topic>/override/` : get manual override ([json data], {"state": "null"} when there's no override)
`<base-topic>/override/set <json data> ` : set/update manual override ( data as refered from API : https://openevse.stoplight.io/docs/openevse-wifi-v4/e0ab0a4ad5e1e-set-the-manual-override )
`<base-topic>/override/` : get manual override ([json data], `{"state": "null"}` when there's no override)
`<base-topic>/override/set <json data>` : set/update manual override (data as refered from API : <https://openevse.stoplight.io/docs/openevse-wifi-v4/e0ab0a4ad5e1e-set-the-manual-override>)
`<base-topic>/override/set toggle` : toggle manual override
`<base-topic>/override/set clear` : clear manual override

`<base-topic>/claim/` : get mqtt service claim ([json data], {"state": "null"} when there's no claim )
`<base-topic>/claim/set <json data>` : set/update claim from MQTT service. Has same priority as HTTP service. ( data as refered from API : https://openevse.stoplight.io/docs/openevse-wifi-v4/ebc578ffa7ca7-make-update-an-evse-claim )
`<base-topic>/claim/` : get mqtt service claim ([json data], `{"state": "null"}` when there's no claim)
`<base-topic>/claim/set <json data>` : set/update claim from MQTT service. Has same priority as HTTP service. (data as refered from API : <https://openevse.stoplight.io/docs/openevse-wifi-v4/ebc578ffa7ca7-make-update-an-evse-claim>)
`<base-topic>/claim/set release` : release claim

Claim & override properties can be set independantly. Sending json with only some fields will update the current claim properties only.
Claim & override properties can be set independantly. Sending json with only some fields will update the current claim properties only.
To remove a selected claim/override property, just send "clear" as property parameter ( i.e. `<base-topic>/claim/set {"charge_current": "clear"}` )

Scheduler data:
`<base-topic>/schedule/` : get scheduler data ([json data]
`<base-topic>/schedule/set <json data>` : set/update schedules ( data as refered from API: https://openevse.stoplight.io/docs/openevse-wifi-v4/e87e6f3f90787-batch-update-schedule )
`<base-topic>/schedule/clear <id> :`remove related event
`<base-topic>/schedule/` : get scheduler data ([json data], `{"state": "null"}` when there's no shcedule)
`<base-topic>/schedule/set <json data>` : set/update schedules ( data as refered from API: <https://openevse.stoplight.io/docs/openevse-wifi-v4/e87e6f3f90787-batch-update-schedule>)
`<base-topic>/schedule/clear <id>` : remove related event

Limit:
`<base-topic>/limit/` : get limit data ([json data]
`<base-topic>/limit/set <json data>` : set/update limit ( data as refered from API:https://openevse.stoplight.io/docs/openevse-wifi-v4/c410fb5e48294-set-charge-limit )
`<base-topic>/limit/set clear` : clear current limit
`<base-topic>/limit/` : get limit data ([json data], `{"state": "null"}` when there's no limit)
`<base-topic>/limit/set <json data>` : set/update limit ( data as refered from API: <https://openevse.stoplight.io/docs/openevse-wifi-v4/c410fb5e48294-set-charge-limit>)
`<base-topic>/limit/set clear` : clear current limit

Main settings:

`<base-topic>/divertmode/set [1 | 2]` : enable (1)/ disable (2) divert mode
`<base-topic>/shaper/set [0 | 1]` : temporary enable (1)/ disable (0) current shaper ( doesn't survive reboot )
`<base-topic>/divertmode/set [1 | 2]` : enable (1)/ disable (2) divert mode
`<base-topic>/shaper/set [0 | 1]` : temporary enable (1)/ disable (0) current shaper ( doesn't survive reboot )
`<base-topic>/restart {"device": "gateway|evse"}` : restart the gateway or openevse module

Config:

`<base-topic>/config_version` : a volatile counter incremented for each config change
`<base-topic>/config` : expose the configuration as a json object

`<base-topic>/config_version` : a volatile counter incremented for each config change
`<base-topic>/config` : expose the configuration as a json object

MQTT setup is pre-populated with OpenEnergyMonitor [emonPi default MQTT server credentials](https://guide.openenergymonitor.org/technical/credentials/#mqtt).

Expand All @@ -69,3 +68,36 @@ MQTT setup is pre-populated with OpenEnergyMonitor [emonPi default MQTT server c
* After a few seconds `Connected: No` should change to `Connected: Yes` if connection is successful. Re-connection will be attempted every 10s. A refresh of the page may be needed.

*Note: `emon/xxxx` should be used as the base-topic if posting to emonPi MQTT server if you want the data to appear in emonPi Emoncms. See [emonPi MQTT docs](https://guide.openenergymonitor.org/technical/mqtt/).*

## Connecting to Cloud IoT services

### AWS IoT Core

Policy for AWS IoT Core:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:eu-west-2:489072314047:client/openevse-*"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:eu-west-2:489072314047:topicfilter/openevse/*"
},
{
"Effect": "Allow",
"Action": [
"iot:Receive",
"iot:Publish",
"iot:RetainPublish"
],
"Resource": "arn:aws:iot:eu-west-2:489072314047:topic/openevse/*"
}
]
}
```
21 changes: 21 additions & 0 deletions models/Certificate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
title: Certificate defenition
allOf:
- type: object
properties:
id:
type: string
description: 'The certificate ID, 64 bit hex number as a string'
name:
type: string
description: 'The human readable certificate name'
type:
type: string
description: 'The certificate type'
certificate:
type: string
description: 'A PEM formatted certificate'
private_key:
type: string
description: 'A PEM formatted private key'
x-tags:
- Certificates
3 changes: 3 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ debug_flags =
#-D ENABLE_DEBUG_MICROTASKS
#-D ENABLE_DEBUG_ENERGY_METER
#-D ENABLE_DEBUG_MEMORY_MONITOR
#-D ENABLE_DEBUG_CETRIFICATES
#-D ENABLE_DEBUG_WEB_CETRIFICATES
#-D ENABLE_DEBUG_MONGOOSE_MQTT_CLIENT
src_build_flags =
# -D ARDUINOJSON_USE_LONG_LONG
# -D ENABLE_ASYNC_WIFI_SCAN
Expand Down
4 changes: 4 additions & 0 deletions src/app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ String lang;
// Web server authentication (leave blank for none)
String www_username;
String www_password;
String www_certificate_id;

// Advanced settings
String esp_hostname;
Expand All @@ -66,6 +67,7 @@ uint32_t mqtt_port;
String mqtt_topic;
String mqtt_user;
String mqtt_pass;
String mqtt_certificate_id;
String mqtt_solar;
String mqtt_grid_ie;
String mqtt_vrms;
Expand Down Expand Up @@ -153,6 +155,7 @@ ConfigOpt *opts[] =
// Web server authentication (leave blank for none)
new ConfigOptDefinition<String>(www_username, "", "www_username", "au"),
new ConfigOptSecret(www_password, "", "www_password", "ap"),
new ConfigOptDefenition<String>(www_certificate_id, "", "www_certificate_id", "wc"),

// Advanced settings
new ConfigOptDefinition<String>(esp_hostname, esp_hostname_default, "hostname", "hn"),
Expand All @@ -177,6 +180,7 @@ ConfigOpt *opts[] =
new ConfigOptDefinition<String>(mqtt_topic, esp_hostname, "mqtt_topic", "mt"),
new ConfigOptDefinition<String>(mqtt_user, "emonpi", "mqtt_user", "mu"),
new ConfigOptSecret(mqtt_pass, "emonpimqtt2016", "mqtt_pass", "mp"),
new ConfigOptDefinition<String>(mqtt_certificate_id, "", "mqtt_certificate_id", "mct"),
new ConfigOptDefinition<String>(mqtt_solar, "", "mqtt_solar", "mo"),
new ConfigOptDefinition<String>(mqtt_grid_ie, "emon/emonpi/power1", "mqtt_grid_ie", "mg"),
new ConfigOptDefinition<String>(mqtt_vrms, "emon/emonpi/vrms", "mqtt_vrms", "mv"),
Expand Down
Loading
Loading