SolarUser Secrets API - SolarNetwork/solarnetwork GitHub Wiki
The SolarUser Secrets API provides methods to manage account-wide sensitive passwords for use by other systems within SolarNetwork, such as Cloud Integration expressions.
The SolarUser Secrets API works by using public-key cryptography to encrypt sensitive information, like passwords to remote systems, before storing it within SolarNetwork. You first upload one or more public and private key pairs to SolarNetwork, which stores them in a key store encrypted with a password you provide. The password you provide is stored securely in a separate secret store. Once you have saved a key pair you can then upload secrets that specify which key pair it should be encrypted with, and SolarNetwork then uses that key pair's public key to encrypt the secret value before saving it.
When a system within SolarNetwork needs to use a secret value, it looks up the appropriate key pair to use, then gets the password needed to decrypt its key store from the secret store, then decrypts the key store to obtain its private key which it then uses to decrypt the secret value.
SolarNetwork takes security seriously; this section provides more detail on the mechanisms outlined in the previous overview section.
When you upload a key pair, you also provide a password. SolarNetwork takes the password provided and derives a key store encryption key using the HMAC+SHA256 digest algorithm. The key pair is then copied into a PKCS#12 key store archive as a self-signed X.509 certificate, encrypted with that key store encryption key. SolarNetwork then saves the key store to its internal database. The key store encryption key is then saved to the secret store (see the next section).
With this procedure, SolarNetwork does not store the actual password you provided with the key pair, only a one-way digested derivation of it.
The key store encryption key defined in the previous section is saved to the AWS Secrets Manager.
Secret values are encrypted first using AES in GCM mode, using a randomly-generated password. The random password and encrypted secret value are then both encrypted using the public key of the specified key pair, using the RSA algorithm. This final encrypted secret value is then saved to SolarNetwork's internal database.
In order to decrypt a secret value, SolarNetwork must first decrypt the key store associated with the secret, using the key store encryption key obtained from the secret store (AWS Secrets Manager). Then SolarNetwork can decrypt the encrypted secret value using the private key of the key pair stored in the key store. That produces the randomly generated AES password and AES-encrypted secret value, so SolarNetwork can then perform the final AES decryption and return the original plain secret value.
For endpoints that return timestamp values (full date and time) the timestamps will be rendered as
string values using the ISO 8601 timestamp format YYYY-MM-dd HH:mm:ss.SSSSSS'Z'
in the UTC time
zone using a space delimiter between the date and time values, for example 2020-03-01 10:30:49.346827Z
. The fractional second can contain up to 6 digits for nanosecond level precision,
and will only display up to the precision set in the timestamp. That means the fractional seconds
might not appear if the timestamp has no fractional seconds.
For endpoints that accept timestamp values, the same ISO 8601 timestamp format is required, however
the fractional seconds may be omitted. For example 2020-03-01 10:30:49Z
is a valid value.
Alternatively the ISO 8601 form using a T
delimiter between the date and time values can be used,
for example 2020-03-01T10:30:49Z
. Alternatively a millisecond Unix epoch number value can be used,
for example 1583058649000
.
The following endpoint paths are all relative to the base path /solaruser/api/v1/sec/user/secrets
.
API group | Description |
---|---|
/key-pair |
Key pair management |
/secret |
Secret management |
Key pairs are RSA public/private keys, identified by a unique name. The public key is used for encryption; the private key is used for decryption. SolarNetwork stores each key pair in an encrypted form, using a password that you provide when saving the key pair in SolarNetwork.
The following endpoint paths are all relative to the base path /solaruser/api/v1/sec/user/secrets
.
Verb | Endpoint | Description |
---|---|---|
POST |
/key-pair |
Save a key pair |
GET |
/key-pair |
List key pairs |
DELETE |
/key-pair |
Delete a key pair |
This method creates or updates a KeyPair entity. An application/json
request body must be provided with
the details to save.
POST | /solaruser/api/v1/sec/user/secrets/key-pair |
---|
The request body must be a JSON object with the following properties:
Property | Type | Description |
---|---|---|
key |
String | The account-wide unique name for the key pair. |
keyPem |
String | PEM-encoded key pair data. |
password |
String | A password to encrypt the key pair with. |
For example:
{
"key": "c2c/i9n",
"keyPem": "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDG5hIi3Ul9NouUAZsC1Wld3YyR0h2Qg61vry1faabnjOqn1tWE...\n-----END RSA PRIVATE KEY-----",
"password": "foobar"
}
☝️ Note that the PEM encoded key information must be provided in unencrypted form. The
password
value will be used by SolarNetwork to encrypt the key pair.
The response will be a KeyPair entity object.
One method of generating a suitable pemKey
value is to ues OpenSSL, like this:
openssl genrsa 1024
That will output a suitable keyPem
value. Another method is to use OpenSSH, like this:
ssh-keygen -m PEM -t rsa -b 1024 -f my-key.pem
☝️ When asked to enter a passphrase, just type Enter to save the key in unencrypted form, which is what SolarNetwork requires.
Also note that this command will generate a
my-key.pem.pub
file, which you will not need.
This method returns a list of KeyPair entities matching an optional search criteria.
GET | /solaruser/api/v1/sec/user/secrets/key-pair |
---|---|
key |
The name of the secret to match. |
keys |
A comma-delimited list of names to match (logical OR). |
offset |
Optional starting result offset. Defaults to 0 . |
max |
Optional maximum result count, or unlimited if not provided. |
The response will be a paged results list of KeyPair entity objects.
An example response looks like:
{
"success": true,
"data": {
"totalResults": 1,
"startingOffset": 0,
"returnedResultCount": 1,
"results": [
{
"userId": 123,
"key": "c2c/i9n",
"created": "2025-03-23 00:35:09.383563Z",
"modified": "2025-03-23 00:35:09.383563Z"
}
]
}
}
A KeyPair entity is an object with the following properties:
Property | Type | Description |
---|---|---|
userId |
Number | The SolarNetwork account ID that owns the entity. |
key |
String | A unique name assigned to the entity. |
created |
String | The creation date. |
modified |
String | The modification date. |
☝️ Note the key store data is not returned by the API.
This method deletes a KeyPair entity.
DELETE | /solaruser/api/v1/sec/user/secrets/key-pair |
---|---|
key |
The name of the key pair to delete. |
The response will be a simple success or failure message.
Secrets are small data values (like passwords) that are saved in an encrypted form, using a KeyPair entity to encrypt and decrypt them.
The following endpoint paths are all relative to the base path /solaruser/api/v1/sec/user/secrets
.
Verb | Endpoint | Description |
---|---|---|
POST |
/secret |
Save a secret |
GET |
/secret |
List secrets |
DELETE |
/secret |
Delete a secret |
This method creates or updates a Secret entity. An application/json
request body must be provided
with the details to save.
POST | /solaruser/api/v1/sec/user/secrets/secret |
---|
The request body must be a JSON object with the following properties:
Property | Type | Description |
---|---|---|
topic |
String | A reference to a KeyPair entity key value. |
key |
String | The account-wide unique name for the secret. |
secretBase64 |
String | The secret value as a Base64-encoded string. |
secretHex |
String | The secret value as a hex-encoded string. |
secretValue |
String | The secret value as a string. |
☝️ Only one
secret*
propery needs to be provided. The different properties are supported so you can provide the secret value in the most suitable format.
For example:
{
"topic": "c2c/i9n",
"key": "my-service-password",
"secretValue": "foobar"
}
The response will be a Secret entity object.
This method returns a list of Secret entities matching optional search criteria.
GET | /solaruser/api/v1/sec/user/secrets/secret |
---|---|
topic |
A topic to match. |
topics |
A comma-delimited list of topics to match (logic OR). |
key |
The name of the secret to match. |
keys |
A comma-delimited list of names to match (logical OR). |
offset |
Optional starting result offset. Defaults to 0 . |
max |
Optional maximum result count, or unlimited if not provided. |
The response will be a paged results list of Secret entity objects.
An example response looks like:
{
"success": true,
"data": {
"totalResults": 1,
"startingOffset": 0,
"returnedResultCount": 1,
"results": [
{
"userId": 123,
"topic": "c2c/i9n",
"key": "my-service-password",
"created": "2025-03-23 00:46:49.132139Z",
"modified": "2025-03-23 00:46:49.132139Z"
}
]
}
}
☝️ Note the secret value is not returned by the API.
A Secret entity is an object with the following properties:
Property | Type | Description |
---|---|---|
userId |
Number | The SolarNetwork account ID that owns the entity. |
topic |
String | A reference to a KeyPair entity key value. |
key |
String | A unique name assigned to the entity. |
created |
String | The creation date. |
modified |
String | The modification date. |
This method deletes a Secret entity.
DELETE | /solaruser/api/v1/sec/user/secrets/secret |
---|---|
topic |
The topic of the secret to delete. |
key |
The name of the secret to delete. |
The response will be a simple success or failure message.