-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
e2e tests: Added the e2e test folder and included the docker compose …
…file with Everest configurations
- Loading branch information
1 parent
9f5b969
commit 3936fde
Showing
48 changed files
with
3,207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.PHONY: up | ||
up: register-cs setup-rfid setup-contract | ||
OCPP_VERSION=ocpp docker-compose --profile everest up | ||
|
||
.PHONY: test | ||
test: # password 123456 | ||
websocat --client-pkcs12-der ./config/certificates/cs001.pem --client-pkcs12-passwd 123456 wss://localhost:443 | ||
|
||
.PHONY: setup-rfid | ||
setup-rfid: | ||
curl -i http://localhost:9410/api/v0/token -H 'content-type: application/json' -d '{"countryCode": "GB","partyId": "TWK","type": "RFID","uid": "DEADBEEF","contractId": "GBTWK012345678V","issuer": "Thoughtworks","valid": true,"cacheMode": "ALWAYS"}' | ||
|
||
.PHONY: setup-contract | ||
setup-contract: | ||
curl -i http://localhost:9410/api/v0/token -H 'content-type: application/json' -d '{"countryCode": "GB","partyId": "TWK","type": "RFID","uid": "EMP77TWTW99999","contractId": "GBTWK012345678V","issuer": "Thoughtworks","valid": true,"cacheMode": "ALWAYS"}' | ||
|
||
.PHONY: register-cs | ||
register-cs: | ||
curl -i http://localhost:9410/api/v0/cs/cs001 -H 'content-type: application/json' -d '{"securityProfile":2}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# End-to-End test | ||
|
||
We currently use two different versions of EVerest and the MQTT API for RFID authorisation | ||
is different between them: if using the older "v5" image (the default): | ||
|
||
```shell | ||
$ NO_AUTH_TOKEN_TYPE_PREFIX=1 go test -v ./... -count=1 | ||
``` | ||
|
||
Otherwise, | ||
|
||
```shell | ||
$ go test -v ./... -count=1 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
version: "3.5" | ||
|
||
networks: | ||
default: | ||
name: maeve-csms | ||
external: true | ||
|
||
services: | ||
mqtt-server: | ||
image: ghcr.io/everest/everest-demo/mqtt-server:0.0.10 | ||
logging: | ||
driver: none | ||
ports: | ||
- "1884:1883" | ||
- "9001:9000" | ||
user: "10000:10000" | ||
healthcheck: | ||
test: [ "CMD-SHELL", "timeout 5 mosquitto_sub -t '$$SYS/#' -C 1 | grep -v Error || exit 1" ] | ||
interval: 10s | ||
timeout: 10s | ||
retries: 3 | ||
|
||
manager: | ||
image: ghcr.io/everest/everest-demo/manager:0.0.10 | ||
depends_on: | ||
- mqtt-server | ||
environment: | ||
MQTT_SERVER_ADDRESS: mqtt-server | ||
entrypoint: "sh ./build/run-scripts/run-sil-${OCPP_VERSION}.sh" | ||
sysctls: | ||
- net.ipv6.conf.all.disable_ipv6=0 | ||
volumes: | ||
- type: bind | ||
source: ./everest/config/everest | ||
target: /ext/source/config | ||
- type: bind | ||
source: ./everest/config/everest/ocpp/OCPP | ||
target: /workspace/dist/share/everest/modules/OCPP | ||
- type: bind | ||
source: ./everest/config/everest/ocpp/OCPP201 | ||
target: /workspace/dist/share/everest/modules/OCPP201 | ||
- type: bind | ||
source: ./everest/config/everest/certs | ||
target: /workspace/dist/etc/everest/certs | ||
|
||
nodered: | ||
image: ghcr.io/everest/everest-demo/nodered:0.0.10 | ||
depends_on: | ||
- mqtt-server | ||
environment: | ||
- MQTT_SERVER_ADDRESS=mqtt-server | ||
- FLOWS=/config/config-sil-two-evse-flow.json | ||
ports: | ||
- 1880:1880 | ||
sysctls: | ||
- net.ipv6.conf.all.disable_ipv6=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
mqtt "github.com/eclipse/paho.mqtt.golang" | ||
"os" | ||
"sync" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { | ||
c := make(chan struct{}) | ||
go func() { | ||
defer close(c) | ||
wg.Wait() | ||
}() | ||
select { | ||
case <-c: | ||
return false // completed normally | ||
case <-time.After(timeout): | ||
return true // timed out | ||
} | ||
} | ||
|
||
func shutdownBrokerConnection(t *testing.T, client mqtt.Client, wg *sync.WaitGroup) { | ||
defer client.Disconnect(0) | ||
|
||
t.Log("unplugging...") | ||
wg.Add(1) | ||
tok := client.Publish("everest_external/nodered/1/carsim/cmd/modify_charging_session", 0, false, "unplug") | ||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Errorf("failed to publish unplug to topic: %v", tok.Error()) | ||
} | ||
timedOut := waitTimeout(wg, 5*time.Second) | ||
if timedOut { | ||
t.Errorf("timed out waiting for unplug to complete") | ||
} | ||
} | ||
|
||
func setupBrokerConnection(t *testing.T, wg *sync.WaitGroup) (mqtt.Client, func()) { | ||
brokerAddr := os.Getenv("MQTT_BROKER_ADDR") | ||
if brokerAddr == "" { | ||
brokerAddr = "localhost:1884" | ||
} | ||
|
||
opts := mqtt.NewClientOptions() | ||
opts.AddBroker(brokerAddr) | ||
|
||
client := mqtt.NewClient(opts) | ||
if token := client.Connect(); token.WaitTimeout(2*time.Second) && token.Error() != nil { | ||
t.Fatalf("failed to connect to MQTT broker: %v", token.Error()) | ||
} | ||
|
||
return client, func() { | ||
shutdownBrokerConnection(t, client, wg) | ||
} | ||
} | ||
|
||
func TestRFIDCharge(t *testing.T) { | ||
// we currently use two different versions of EVerest and the MQTT API for RFID authorisation is different | ||
// between them: if using the older "v5" image (the default) set the environment variable NO_AUTH_TOKEN_TYPE_PREFIX | ||
|
||
wg := sync.WaitGroup{} | ||
|
||
client, shutdown := setupBrokerConnection(t, &wg) | ||
defer shutdown() | ||
|
||
state := "Unset" | ||
|
||
tok := client.Subscribe("everest_external/nodered/1/state/state_string", 0, func(client mqtt.Client, msg mqtt.Message) { | ||
t.Logf("charger status changed to %s\n", msg.Payload()) | ||
|
||
switch string(msg.Payload()) { | ||
case "Wait for Auth": | ||
state = string(msg.Payload()) | ||
wg.Done() | ||
case "Charging": | ||
state = string(msg.Payload()) | ||
wg.Done() | ||
case "Idle": | ||
state = string(msg.Payload()) | ||
wg.Done() | ||
} | ||
}) | ||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Fatalf("failed to subscribe to topic: %v", tok.Error()) | ||
} | ||
|
||
wg.Add(1) | ||
t.Logf("plug in...") | ||
tok = client.Publish("everest_external/nodered/1/carsim/cmd/execute_charging_session", 0, false, | ||
"sleep 1;iec_wait_pwr_ready;sleep 1;draw_power_regulated 16,3;sleep 5") | ||
|
||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Fatalf("failed to publish start charge to topic: %v", tok.Error()) | ||
} | ||
|
||
timedOut := waitTimeout(&wg, 5*time.Second) | ||
if timedOut { | ||
t.Errorf("timed out waiting for ready to authorise") | ||
} | ||
if state != "Wait for Auth" { | ||
t.Fatalf("expected state to be Wait for Auth, got %s", state) | ||
} | ||
|
||
wg.Add(1) | ||
t.Logf("authorise charge...") | ||
tok = client.Publish("everest_api/dummy_token_provider/cmd/provide", 0, false, | ||
fmt.Sprintf("{\"id_token\":\"DEADBEEF\",\"authorization_type\":\"RFID\",\"prevalidated\":false,\"connectors\":[1]}")) | ||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Fatalf("failed to publish authorise to topic: %v", tok.Error()) | ||
} | ||
|
||
timedOut = waitTimeout(&wg, 5*time.Second) | ||
if timedOut { | ||
t.Errorf("timed out waiting for authorise to complete") | ||
} | ||
if state != "Charging" { | ||
t.Fatalf("expected state to be Charging, got %s", state) | ||
} | ||
} | ||
|
||
func TestISO15118Charge(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("skipping test in short mode.") | ||
} | ||
wg := sync.WaitGroup{} | ||
|
||
client, shutdown := setupBrokerConnection(t, &wg) | ||
defer shutdown() | ||
|
||
state := "Unset" | ||
|
||
tok := client.Subscribe("everest_external/nodered/1/state/state_string", 0, func(client mqtt.Client, msg mqtt.Message) { | ||
t.Logf("charger status changed to %s\n", msg.Payload()) | ||
|
||
switch string(msg.Payload()) { | ||
case "PrepareCharging": | ||
state = string(msg.Payload()) | ||
wg.Done() | ||
case "Idle": | ||
state = string(msg.Payload()) | ||
wg.Done() | ||
} | ||
}) | ||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Fatalf("failed to subscribe to topic: %v", tok.Error()) | ||
} | ||
|
||
wg.Add(1) | ||
t.Logf("plug in...") | ||
tok = client.Publish("everest_external/nodered/1/carsim/cmd/execute_charging_session", 0, false, | ||
"sleep 1;iso_wait_slac_matched;iso_start_v2g_session Contract,AC_three_phase_core;iso_wait_pwr_ready;iso_draw_power_regulated 16,3;sleep 36000") | ||
if tok.WaitTimeout(1 * time.Second); tok.Error() != nil { | ||
t.Fatalf("failed to publish start charge to topic: %v", tok.Error()) | ||
} | ||
|
||
timedOut := waitTimeout(&wg, 15*time.Second) | ||
if timedOut { | ||
t.Errorf("timed out waiting for charge to start") | ||
} | ||
if state != "PrepareCharging" { | ||
t.Fatalf("expected state to be PrepareCharging, got %s", state) | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
e2e-tests/everest/config/certificates/HUBOpenProvCert001.pem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIB9jCCAZygAwIBAgIQXAGaGc0odduhH6YnK05NazAKBggqhkjOPQQDAjBDMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMR0wGwYDVQQDExRNTyBT | ||
dWIyIENBIFFBIEcxLjIuMTAeFw0yMzA1MjMxMjU1NTNaFw0yNDAzMDEwMDAwMDBa | ||
MCsxEDAOBgNVBAoTB0h1YmplY3QxFzAVBgNVBAMTDkVNUDc3VFdUVzAwMDAyMFkw | ||
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUVJxF0Z81GW4LZ3fnvC+z5fn7QvPe+nx | ||
ZBOGtzpB6RRmafqwTL9ctzWMMkaB6nuIUyyTKR0Rs+XKYJeToK7S8qOBiTCBhjAP | ||
BgNVHRMBAf8EBTADAQEAMBEGA1UdDgQKBAhGBfp1bBhxXDATBgNVHSMEDDAKgAhF | ||
LmmhNiJsSDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vY3Nw | ||
LXFhLmh1YmplY3QuY29tOjgwODAwDgYDVR0PAQH/BAQDAgPoMAoGCCqGSM49BAMC | ||
A0gAMEUCIBV5rlKEeHjernJPfzxA3HyPH742YcS8oEmUlWccrH62AiEAln/HGazM | ||
NZqhoS5SSscViysAOQGvvcjHMKucJ5CjdLg= | ||
-----END CERTIFICATE----- | ||
subject=/C=DE/O=Hubject GmbH/CN=MO Sub2 CA QA G1.2.1 | ||
issuer=/C=DE/O=Hubject GmbH/CN=MO Sub1 CA QA G1.2 | ||
-----BEGIN CERTIFICATE----- | ||
MIICDzCCAbWgAwIBAgIQXd9CzQy8+VxpQt9IwNrOETAKBggqhkjOPQQDAjBBMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMRswGQYDVQQDExJNTyBT | ||
dWIxIENBIFFBIEcxLjIwHhcNMjIwNDEwMjE1OTU5WhcNMzIwNDEwMjE1OTU5WjBD | ||
MQswCQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMR0wGwYDVQQDExRN | ||
TyBTdWIyIENBIFFBIEcxLjIuMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGRs | ||
p5TTDIGpB+PEwmeG8D7Pgo/WN3U35Rxhe5ttLLlyF2jlmtOPHeHxWgGb0AO7H3L6 | ||
nso0A7Nn2KfDP8tG+OujgYwwgYkwEgYDVR0TAQH/BAgwBgEB/wIBADARBgNVHQ4E | ||
CgQIRS5poTYibEgwEwYDVR0jBAwwCoAISw94EhgPO18wOwYIKwYBBQUHAQEELzAt | ||
MCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC1xYS5odWJqZWN0LmNvbTo4MDgwMA4G | ||
A1UdDwEB/wQEAwIBxjAKBggqhkjOPQQDAgNIADBFAiBqFxXTwnpm0eEgBPj/Px0k | ||
aEvZWdyZPm7BLJVJM6fT3QIhAKZPDhuau2DcN9xrrRPqqZLjfqPSMWw1D0VlCTqC | ||
uv2k | ||
-----END CERTIFICATE----- | ||
|
||
subject=/C=DE/O=Hubject GmbH/CN=MO Sub1 CA QA G1.2 | ||
issuer=/C=DE/O=Hubject GmbH/DC=V2G/CN=V2G Root CA QA G1 | ||
-----BEGIN CERTIFICATE----- | ||
MIICIjCCAcegAwIBAgIQIOuk+8fAbyXQizBVpSI55zAKBggqhkjOPQQDAjBVMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMRMwEQYKCZImiZPyLGQB | ||
GRYDVjJHMRowGAYDVQQDExFWMkcgUm9vdCBDQSBRQSBHMTAeFw0yMjA0MDcxNDEz | ||
MDdaFw00MjA0MDcxNDEzMDdaMEExCzAJBgNVBAYTAkRFMRUwEwYDVQQKEwxIdWJq | ||
ZWN0IEdtYkgxGzAZBgNVBAMTEk1PIFN1YjEgQ0EgUUEgRzEuMjBZMBMGByqGSM49 | ||
AgEGCCqGSM49AwEHA0IABLWnWSw4NPNInduDQp6H0IFgeY0WtO0F3utqV191XLIe | ||
spoAoSIz7s4Vhf+BhbbeX+UyftbGDp2m9EjGIBhog+mjgYwwgYkwEgYDVR0TAQH/ | ||
BAgwBgEB/wIBATARBgNVHQ4ECgQISw94EhgPO18wEwYDVR0jBAwwCoAIS0X/giX8 | ||
EJYwOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC1xYS5o | ||
dWJqZWN0LmNvbTo4MDgwMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAgNJADBG | ||
AiEAsApDKLvPUVuDCtsIAnn/+prsGu5aekwd59tLiCHAFwACIQCFGJHvTz7JUrq/ | ||
QJhQzehduW/+oaROsqOp8L3JdEO6XA== | ||
-----END CERTIFICATE----- | ||
|
47 changes: 47 additions & 0 deletions
47
e2e-tests/everest/config/certificates/HUBOpenProvCert002.pem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIB9jCCAZygAwIBAgIQWg+8k4JcqPIZeX5bj3LoBzAKBggqhkjOPQQDAjBDMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMR0wGwYDVQQDExRNTyBT | ||
dWIyIENBIFFBIEcxLjIuMTAeFw0yMzA1MjMxMjU3MDlaFw0yNDAzMDEwMDAwMDBa | ||
MCsxEDAOBgNVBAoTB0h1YmplY3QxFzAVBgNVBAMTDkVNUDc3VFdUVzAwMDAzMFkw | ||
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKsUiYDu/OGHjKEq39spSiS6CdE9q4jg6 | ||
ysuA3ACCKCH5S9Y8YGqy73Dy+fHUZpdzFOAPoYJEK4srYAwgH221z6OBiTCBhjAP | ||
BgNVHRMBAf8EBTADAQEAMBEGA1UdDgQKBAhJFUMGc8ldDzATBgNVHSMEDDAKgAhF | ||
LmmhNiJsSDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vY3Nw | ||
LXFhLmh1YmplY3QuY29tOjgwODAwDgYDVR0PAQH/BAQDAgPoMAoGCCqGSM49BAMC | ||
A0gAMEUCIBYBkDz5gexjKLYJsQZua4AktjO6IqYSFXp9bJ2MOE6/AiEA3iAuGdty | ||
i24pSc5F8qCbDQKnNASWWMrFVOOJFVh1n7c= | ||
-----END CERTIFICATE----- | ||
subject=/C=DE/O=Hubject GmbH/CN=MO Sub2 CA QA G1.2.1 | ||
issuer=/C=DE/O=Hubject GmbH/CN=MO Sub1 CA QA G1.2 | ||
-----BEGIN CERTIFICATE----- | ||
MIICDzCCAbWgAwIBAgIQXd9CzQy8+VxpQt9IwNrOETAKBggqhkjOPQQDAjBBMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMRswGQYDVQQDExJNTyBT | ||
dWIxIENBIFFBIEcxLjIwHhcNMjIwNDEwMjE1OTU5WhcNMzIwNDEwMjE1OTU5WjBD | ||
MQswCQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMR0wGwYDVQQDExRN | ||
TyBTdWIyIENBIFFBIEcxLjIuMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGRs | ||
p5TTDIGpB+PEwmeG8D7Pgo/WN3U35Rxhe5ttLLlyF2jlmtOPHeHxWgGb0AO7H3L6 | ||
nso0A7Nn2KfDP8tG+OujgYwwgYkwEgYDVR0TAQH/BAgwBgEB/wIBADARBgNVHQ4E | ||
CgQIRS5poTYibEgwEwYDVR0jBAwwCoAISw94EhgPO18wOwYIKwYBBQUHAQEELzAt | ||
MCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC1xYS5odWJqZWN0LmNvbTo4MDgwMA4G | ||
A1UdDwEB/wQEAwIBxjAKBggqhkjOPQQDAgNIADBFAiBqFxXTwnpm0eEgBPj/Px0k | ||
aEvZWdyZPm7BLJVJM6fT3QIhAKZPDhuau2DcN9xrrRPqqZLjfqPSMWw1D0VlCTqC | ||
uv2k | ||
-----END CERTIFICATE----- | ||
|
||
subject=/C=DE/O=Hubject GmbH/CN=MO Sub1 CA QA G1.2 | ||
issuer=/C=DE/O=Hubject GmbH/DC=V2G/CN=V2G Root CA QA G1 | ||
-----BEGIN CERTIFICATE----- | ||
MIICIjCCAcegAwIBAgIQIOuk+8fAbyXQizBVpSI55zAKBggqhkjOPQQDAjBVMQsw | ||
CQYDVQQGEwJERTEVMBMGA1UEChMMSHViamVjdCBHbWJIMRMwEQYKCZImiZPyLGQB | ||
GRYDVjJHMRowGAYDVQQDExFWMkcgUm9vdCBDQSBRQSBHMTAeFw0yMjA0MDcxNDEz | ||
MDdaFw00MjA0MDcxNDEzMDdaMEExCzAJBgNVBAYTAkRFMRUwEwYDVQQKEwxIdWJq | ||
ZWN0IEdtYkgxGzAZBgNVBAMTEk1PIFN1YjEgQ0EgUUEgRzEuMjBZMBMGByqGSM49 | ||
AgEGCCqGSM49AwEHA0IABLWnWSw4NPNInduDQp6H0IFgeY0WtO0F3utqV191XLIe | ||
spoAoSIz7s4Vhf+BhbbeX+UyftbGDp2m9EjGIBhog+mjgYwwgYkwEgYDVR0TAQH/ | ||
BAgwBgEB/wIBATARBgNVHQ4ECgQISw94EhgPO18wEwYDVR0jBAwwCoAIS0X/giX8 | ||
EJYwOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzABhh9odHRwOi8vb2NzcC1xYS5o | ||
dWJqZWN0LmNvbTo4MDgwMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAgNJADBG | ||
AiEAsApDKLvPUVuDCtsIAnn/+prsGu5aekwd59tLiCHAFwACIQCFGJHvTz7JUrq/ | ||
QJhQzehduW/+oaROsqOp8L3JdEO6XA== | ||
-----END CERTIFICATE----- | ||
|
Oops, something went wrong.