Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 8 additions & 8 deletions .github/workflows/test-and-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ jobs:
run: |
npx cdk --app "npx tsx --no-warnings cdk/test-resources.ts" deploy --require-approval never
MOCK_HTTP_API_ENDPOINT=`aws cloudformation describe-stacks --stack-name ${{ env.STACK_NAME }}-test | jq -r '.Stacks[0].Outputs[] | select(.OutputKey == "apiURL") | .OutputValue' | sed -E 's/\/$//g'`
./cli.sh configure thirdParty/acme/apiEndpoint ${MOCK_HTTP_API_ENDPOINT}
./cli.sh configure thirdParty/acme/apiKey apiKey_Acme
./cli.sh configure thirdParty/elite/apiEndpoint ${MOCK_HTTP_API_ENDPOINT}
./cli.sh configure thirdParty/elite/apiKey apiKey_Elite
./cli.sh configure-nrfcloud-account acme apiEndpoint ${MOCK_HTTP_API_ENDPOINT}
./cli.sh configure-nrfcloud-account acme apiKey apiKey_Acme
./cli.sh configure-nrfcloud-account elite apiEndpoint ${MOCK_HTTP_API_ENDPOINT}
./cli.sh configure-nrfcloud-account elite apiKey apiKey_Elite

- name: Deploy solution stack
env:
Expand Down Expand Up @@ -119,11 +119,11 @@ jobs:
npx cdk destroy -f
npx cdk --app 'npx tsx --no-warnings cdk/test-resources.ts' destroy -f
./cli.sh fake-nrfcloud-account-device acme --remove
./cli.sh configure thirdParty/acme/apiEndpoint -X
./cli.sh configure thirdParty/acme/apiKey -X
./cli.sh configure-nrfcloud-account acme apiEndpoint -X
./cli.sh configure-nrfcloud-account acme apiKey -X
./cli.sh fake-nrfcloud-account-device elite --remove
./cli.sh configure thirdParty/elite/apiEndpoint -X
./cli.sh configure thirdParty/elite/apiKey -X
./cli.sh configure-nrfcloud-account elite apiEndpoint -X
./cli.sh configure-nrfcloud-account elite apiKey -X
./cli.sh clean-backup-certificates

release:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ certificate used by MQTT broker to connect nRF Cloud under your account. So, you
need to prepare nRF Cloud API key.

```bash
./cli.sh configure thirdParty/<account>/apiKey <API key>
./cli.sh configure-nrfcloud-account <account> apiKey <API key>
./cli.sh initialize-nrfcloud-account <account>
./cli.sh create-health-check-device <account>
```
Expand Down
9 changes: 7 additions & 2 deletions cdk/resources/ConfigureDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { PackedLambda } from '../helpers/lambdas/packLambda.js'
import { LambdaSource } from './LambdaSource.js'
import type { WebsocketAPI } from './WebsocketAPI.js'
import { Context } from '@hello.nrfcloud.com/proto/hello'
import { Scope } from '../../util/settings.js'

/**
* Handles device configuration requests
Expand Down Expand Up @@ -56,10 +57,14 @@ export class ConfigureDevice extends Construct {
resources: [
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty/*`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}/*`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/nRFCloud/accounts`,
Expand Down
9 changes: 7 additions & 2 deletions cdk/resources/DeviceShadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Construct } from 'constructs'
import type { PackedLambda } from '../helpers/lambdas/packLambda'
import { LambdaSource } from './LambdaSource.js'
import type { WebsocketAPI } from './WebsocketAPI.js'
import { Scope } from '../../util/settings.js'

export class DeviceShadow extends Construct {
public constructor(
Expand Down Expand Up @@ -120,10 +121,14 @@ export class DeviceShadow extends Construct {
resources: [
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty/*`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}/*`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/nRFCloud/accounts`,
Expand Down
9 changes: 7 additions & 2 deletions cdk/resources/HealthCheckMqttBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { PackedLambda } from '../helpers/lambdas/packLambda.js'
import type { DeviceStorage } from './DeviceStorage.js'
import type { WebsocketAPI } from './WebsocketAPI.js'
import { LambdaSource } from './LambdaSource.js'
import { Scope } from '../../util/settings.js'

export type BridgeImageSettings = BridgeSettings

Expand Down Expand Up @@ -64,10 +65,14 @@ export class HealthCheckMqttBridge extends Construct {
resources: [
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty/*`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}/*`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/nRFCloud/accounts`,
Expand Down
2 changes: 1 addition & 1 deletion cdk/resources/Integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export class Integration extends Construct {
const { environment, secrets } = Object.entries(nRFCloudAccounts).reduce(
(result, [account], index) => {
const bridgeNo = String(index + 2).padStart(2, '0')
const scope = `thirdParty/${account}`
const scope = `${Scope.NRFCLOUD_ACCOUNT_PREFIX}/${account}`
const bridgePrefix = `MOSQUITTO__BRIDGE${bridgeNo}`

result.environment[
Expand Down
9 changes: 7 additions & 2 deletions cdk/resources/SingleCellGeoLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { LambdaSource } from './LambdaSource.js'
import type { WebsocketAPI } from './WebsocketAPI.js'
import { IoTActionRole } from './IoTActionRole.js'
import type { DeviceStorage } from './DeviceStorage.js'
import { Scope } from '../../util/settings.js'

/**
* Resolve device geo location based on network information
Expand Down Expand Up @@ -61,10 +62,14 @@ export class SingleCellGeoLocation extends Construct {
resources: [
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/thirdParty/*`,
}:parameter/${Stack.of(this).stackName}/${
Scope.NRFCLOUD_ACCOUNT_PREFIX
}/*`,
`arn:aws:ssm:${Stack.of(this).region}:${
Stack.of(this).account
}:parameter/${Stack.of(this).stackName}/nRFCloud/accounts`,
Expand Down
4 changes: 2 additions & 2 deletions cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { STACK_NAME } from '../cdk/stacks/stackConfig.js'
import psjon from '../package.json'
import type { CommandDefinition } from './commands/CommandDefinition'
import { configureDeviceCommand } from './commands/configure-device.js'
import { configureCommand } from './commands/configure.js'
import { createFakeNrfCloudAccountDeviceCredentials } from './commands/create-fake-nrfcloud-account-device-credentials.js'
import { createFakeNrfCloudHealthCheckDevice } from './commands/create-fake-nrfcloud-health-check-device.js'
import { createHealthCheckDevice } from './commands/create-health-check-device.js'
Expand All @@ -30,6 +29,7 @@ import { showNRFCloudAccount } from './commands/show-nrfcloud-account.js'
import { simulateDeviceCommand } from './commands/simulate-device.js'
import { cleanBackupCertificates } from './commands/clean-backup-certificates.js'
import { listnRFCloudAccountsCommand } from './commands/list-nrfcloud-accounts.js'
import { configureRFCloudAccountCommand } from './commands/configure-nrfcloud-account.js'

const ssm = new SSMClient({})
const iot = new IoTClient({})
Expand Down Expand Up @@ -60,7 +60,7 @@ const CLI = async ({ isCI }: { isCI: boolean }) => {
program.version(psjon.version)

const commands: CommandDefinition[] = [
configureCommand({ ssm }),
configureRFCloudAccountCommand({ ssm }),
setShadowFetcherCommand({ ssm }),
logsCommand({ stackName: STACK_NAME, cf, logs }),
cleanBackupCertificates({ ssm }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ import { SSMClient } from '@aws-sdk/client-ssm'
import chalk from 'chalk'
import fs from 'fs'
import { STACK_NAME } from '../../cdk/stacks/stackConfig.js'
import { deleteSettings, putSettings } from '../../util/settings.js'
import type { CommandDefinition } from './CommandDefinition.js'
import {
deleteSettings,
putSetting,
type Settings,
} from '../../nrfcloud/settings.js'

export const configureCommand = ({
export const configureRFCloudAccountCommand = ({
ssm,
}: {
ssm: SSMClient
}): CommandDefinition => ({
command: 'configure <path> [value]',
command: 'configure-nrfcloud-account <account> <property> [value]',
options: [
{
flags: '-d, --deleteBeforeUpdate',
Expand All @@ -22,27 +26,18 @@ export const configureCommand = ({
},
],
action: async (
path: string,
account: string,
property: string,
value: string | undefined,
{ deleteBeforeUpdate, deleteParameter },
) => {
const parts = path.split('/')
const property = parts.pop()

const scope = parts.join('/')

if (property === undefined || property.length === 0)
throw new Error(`Must specify a parameter.`)

if (deleteParameter !== undefined) {
// Delete
const { name } = await deleteSettings({
ssm,
stackName: STACK_NAME,
scope,
})({
property,
})
account,
})(property)
console.log()
console.log(
chalk.green('Deleted the parameters from'),
Expand All @@ -56,15 +51,11 @@ export const configureCommand = ({
throw new Error(`Must provide value either as argument or via stdin!`)
}

const { name } = await putSettings({
const { name } = await putSetting({
ssm,
stackName: STACK_NAME,
scope,
})({
property,
value: v,
deleteBeforeUpdate,
})
account,
})(property as keyof Settings, v, deleteBeforeUpdate)

console.log()
console.log(
Expand Down
29 changes: 5 additions & 24 deletions cli/commands/create-fake-nrfcloud-account-device-credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,9 @@ import { chunk } from 'lodash-es'
import { randomUUID } from 'node:crypto'
import { getIoTEndpoint } from '../../aws/getIoTEndpoint.js'
import { STACK_NAME } from '../../cdk/stacks/stackConfig.js'
import { updateSettings, type Settings } from '../../nrfcloud/settings.js'
import { putSettings, type Settings } from '../../nrfcloud/settings.js'
import { isString } from '../../util/isString.js'
import {
Scope,
deleteSettings,
putSettings,
settingsPath,
} from '../../util/settings.js'
import { Scope, settingsPath } from '../../util/settings.js'
import type { CommandDefinition } from './CommandDefinition.js'

export const createFakeNrfCloudAccountDeviceCredentials = ({
Expand All @@ -47,7 +42,7 @@ export const createFakeNrfCloudAccountDeviceCredentials = ({
},
],
action: async (account, { remove }) => {
const scope = `thirdParty/${account}`
const scope = `${Scope.NRFCLOUD_ACCOUNT_PREFIX}/${account}`
const fakeTenantParameter = `/${STACK_NAME}/${account}/fakeTenant`
if (remove === true) {
// check if has fake device
Expand Down Expand Up @@ -131,12 +126,6 @@ export const createFakeNrfCloudAccountDeviceCredentials = ({
)
}

await deleteSettings({
ssm,
stackName: STACK_NAME,
scope: Scope.NRFCLOUD_ACCOUNT,
})({ property: account })

return
}

Expand Down Expand Up @@ -177,25 +166,17 @@ export const createFakeNrfCloudAccountDeviceCredentials = ({
throw new Error(`Failed to create certificate!`)
}

await putSettings({
ssm,
stackName: STACK_NAME,
scope: Scope.NRFCLOUD_ACCOUNT,
})({
property: account,
value: account,
})
const settings: Partial<Settings> = {
accountDeviceClientCert: credentials.certificatePem,
accountDevicePrivateKey: pk,
accountDeviceClientId: `account-${tenantId}`,
mqttEndpoint: await getIoTEndpoint({ iot })(),
mqttTopicPrefix: `prod/${tenantId}/`,
}
await updateSettings({
await putSettings({
ssm,
stackName: STACK_NAME,
scope,
account,
})(settings)

console.debug(chalk.white(`nRF Cloud settings:`))
Expand Down
2 changes: 1 addition & 1 deletion lambda/ws/AuthorizedEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type AuthorizedEvent = APIGatewayProxyWebsocketEventV2 & {
model: string //e.g. "PCA20035+solar",
integrationLatency: 1043
deviceId: string // e.g. 'oob-352656108602296'
account: string // e.g. 'exeger'
account: string // e.g. 'elite'
}
}
}
Expand Down
19 changes: 11 additions & 8 deletions nrfcloud/allAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ export const getAllnRFCloudAccounts = async ({
}: {
ssm: SSMClient
stackName: string
}): Promise<string[]> =>
Object.keys(
await getSettings({
ssm,
stackName,
scope: Scope.NRFCLOUD_ACCOUNT,
})(),
)
}): Promise<string[]> => [
...new Set(
Object.keys(
await getSettings({
ssm,
stackName,
scope: Scope.NRFCLOUD_ACCOUNT_PREFIX,
})(),
).map((key) => key.split('/')[0] as string),
),
]

export const getAllAccountsSettings =
({ ssm, stackName }: { ssm: SSMClient; stackName: string }) =>
Expand Down
10 changes: 7 additions & 3 deletions nrfcloud/healthCheckSettings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { SSMClient } from '@aws-sdk/client-ssm'
import { getSettings as getSSMSettings, putSettings } from '../util/settings.js'
import {
Scope,
getSettings as getSSMSettings,
putSettings,
} from '../util/settings.js'

export type Settings = {
healthCheckClientCert: string
Expand All @@ -21,7 +25,7 @@ export const updateSettings = ({
const settingsWriter = putSettings({
ssm,
stackName,
scope: `thirdParty/${account}`,
scope: `${Scope.NRFCLOUD_ACCOUNT_PREFIX}/${account}`,
})
return async (settings): Promise<void> => {
await Promise.all(
Expand All @@ -44,7 +48,7 @@ export const getSettings = ({
stackName: string
account: string
}): (() => Promise<Settings>) => {
const scope = `thirdParty/${account}`
const scope = `${Scope.NRFCLOUD_ACCOUNT_PREFIX}/${account}`
const settingsReader = getSSMSettings({
ssm,
stackName,
Expand Down
Loading