Graceful Shutdown

0
Hello everyone,   Does anybode now the correct flow go execute a graceful shutdown of an IED? I'm stuck on the step 3: Generate authtoken for accessing the API via auth-api-path + /token/permit with the apptoken as part of the body   I'm using a http request POST url: "https://edge-iot-core.proxy-redirect:8443/a.service/api/v3/token/permit" and I only get 503 Service Unavailable.   Thanks.
asked
2 answers
0

Hi Henrique,

 

Try doing this way:

 

First make sure this is the correct path: "/a.service/api/v3/token/permit

 

Then try doing this way:

curl -k -X POST \  

https://edge-iot-core.proxy-redirect:8443/a.service/api/v3/token/permit \  

-H "Content-Type: application/json" \  

-d '{    "appToken": "<PASTE_REAL_APP_TOKEN_HERE>"  }'

 

This should have the following expected response:

{  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}

 

Save the token for example as:

AUTH_TOKEN

 

Finally try this:

curl -k -X POST \  

https://edge-iot-core.proxy-redirect:8443/a.service/api/v3/device/shutdown \  

-H "Authorization: Bearer <AUTH_TOKEN>"

 

This should have the following expected response:

{  "status": "accepted"}

answered
0

Hey Henrique,

As the current documentation of this feature is a bit sparse, here's a more extensive explanation with implementation examples:

Quick Start: Implementing the Device Shutdown API

Prerequisites

⚠️ Required: Your application must declare the API.Shutdown device feature during version creation:

iectl publisher sa version create \
  -a "myapp" \
  -v "1.0.0" \
  -d "API.Shutdown" \
  ...

Without this flag, the shutdown API will reject your requests with 403 Forbidden.

Overview

The Device Shutdown API allows your app to gracefully shut down an Industrial Edge Device. The process:

  1. Get auth token from device API
  2. Call shutdown endpoint with your parameters
  3. Handle response (or timeout for instant shutdown)

1. Read Configuration Files

Your app needs access to two mounted files:

// Certificate and IP information
certsips := readFile("/var/run/edgedevice/certsips.json")

// Your app's authentication token
appToken := readFile("/etc/edgeconfig/.apptoken")

Certificate structure in certsips.json:

{
  "auth-api-path": "a.service/api/v3",
  "edge-certificates": {
    "certificate-chain": "LS0tLS1CRUdJTi...",
    "service-name": "edge-iot-core.proxy-redirect"
  }
}

Key fields:

  • auth-api-path - Path to auth API (e.g., "a.service/api/v3")
  • edge-certificates.certificate-chain - Internal proxy-redirect certificate as a single base64-encoded string

Note: For on-device apps making internal API calls, only load edge-certificates.certificate-chain. The cert-chain field exists in certsips.json but is only for external clients.

2. Get Authentication Token

Exchange your app token for an access token:

POST https://edge-iot-core.proxy-redirect:443/device/edge/{auth-api-path}/token/permit
Content-Type: application/json

{
  "appPrimaryToken": "your-app-token"
}

Response:

{
  "access_token": "eyJhbGc...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

3. Create TLS Configuration

Extract and decode certificate from certsips.json for secure communication:

import (
    "crypto/tls"
    "crypto/x509"
    "encoding/base64"
)

func createTLSConfig(certsips CertsIPs) (*tls.Config, error) {
    certPool := x509.NewCertPool()

    // Load only internal edge-certificates.certificate-chain
    // We don't need cert-chain (external nginx cert) for internal API calls
    if certsips.EdgeCertificates == nil || certsips.EdgeCertificates.CertificateChain == "" {
        return nil, fmt.Errorf("edge-certificates.certificate-chain not found")
    }

    certPEM, err := base64.StdEncoding.DecodeString(certsips.EdgeCertificates.CertificateChain)
    if err != nil {
        return nil, fmt.Errorf("decoding edge-certificates: %w", err)
    }

    if ok := certPool.AppendCertsFromPEM(certPEM); !ok {
        return nil, fmt.Errorf("failed to parse edge certificate")
    }

    return &tls.Config{
        RootCAs: certPool,
    }, nil
}

4. Call Shutdown API

POST https://edge-iot-core.proxy-redirect:443/device/edge/api/v2/shutdown
Content-Type: application/json
Authorization: Bearer {access_token}

{
  "maxAckTimeForApps": 30,
  "executeNow": true
}

Parameters:

  • maxAckTimeForApps - Seconds to wait for apps to acknowledge (1-30)
  • executeNow - true = immediate shutdown, false = create shutdown job

Expected Responses:

Scenario 1: Job created (executeNow: false)

  • Status: 200
  • Body: Empty
  • Behavior: Device responds, then shuts down after delay

Scenario 2: Instant shutdown (executeNow: true)

  • Status: No response
  • Body: -
  • Behavior: Network dies immediately, request times out

Hope this helps! Let me know if you have any questions.

answered