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

Add environment variable logic #29

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
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Defender as Code Serverless Plugin

Defender as Code (DaC) is a Serverless Framework plugin for automated resource management on Defender.
Defender as Code (DaC) is a Serverless Framework plugin for automated resource management and configuration as code.

:warning: **This plugin is still under development. Bugs are expected. Use with care.**
:warning: This plugin is under development and behavior might change. Handle with care.

## Prerequisites

Expand All @@ -24,6 +24,16 @@ Alternatively, you can install it directly into an existing project with:

## Setup

There are a few ways you can set up the `serverless.yml` configuration:

- Create it from scratch;
- Use Defender's 2.0 Serverless export capability;
- Leverage the example [template](https://github.com/OpenZeppelin/defender-as-code/blob/main/template/serverless.yml) provided in the `defender-as-code` repository.

If you already have resources such as contracts, notifications, relayers, actions, etc. in Defender 2.0, you can export a `serverless.yml` configuration file containing these resources from the manage → advanced page.

NOTE: If you have previously deployed with `defender-as-code` to the same account and subsequently created new resources through the Defender 2.0 user interface, the export function will automatically assign a `stackResourceId` to the new resources based on the name of your latest deployment stack. If you have not deployed using `defender-as-code` before, a default stack name of `mystack` will be used.

This plugin allows you to define Actions, Monitors, Notifications, Categories, Relayers, Contracts, Policies and Secrets declaratively from a `serverless.yml` and provision them via the CLI using `serverless deploy`. An example template below with an action, a relayer, a policy and a single relayer API key defined:

```yaml
Expand Down Expand Up @@ -51,6 +61,10 @@ resources:
type: 'schedule'
frequency: 1500
paused: false
# optional - unencrypted and scoped to the individual action
environment-variables:
hello: 'world!'
action-example-2: 2cbc3f58-d962-4be8-a158-1035be4b661c

policies:
policy-1:
Expand All @@ -76,7 +90,7 @@ This requires setting the `key` and `secret` under the `defender` property of th

Ensure the Defender Team API Keys are setup with all appropriate API capabilities.

The `stackName` (e.g. mystack) is combined with the resource key (e.g. relayer-1) to uniquely identify each resource. This identifier is called the `stackResourceId` (e.g. mystack.relayer-1) and allows you to manage multiple deployments within the same Defender team.
The `stackName` (e.g. mystack) is combined with the resource key (e.g. relayer-1) to uniquely identify each resource. This identifier is called the `stackResourceId` (e.g. mystack.relayer-1) and allows you to manage multiple deployments within the same tenant.

You may also reference existing Defender resources directly by their unique ID (e.g. `2cbc3f58-d962-4be8-a158-1035be4b661c`). These resources will not be managed by the plugin and will be ignored during the deploy process. However, you may reference them in other resources to update their configuration accordingly.
A list of properties that support direct referencing:
Expand Down Expand Up @@ -211,6 +225,8 @@ Errors thrown during the `deploy` process, will not revert any prior changes. Co

Usually, fixing the error and retrying the deploy should suffice as any existing resources will fall within the `update` clause of the deployment. However, if unsure, you can always call `sls remove` to remove the entire stack, and retry.

Action secrets are encrypted key-value pairs and injected at runtime into the lambda environment. Secrets are scoped to all actions automatically. Alternatively, you may use environment-variables to define key-value pairs that are scoped to the individual action, and available at runtime through `process.env`. Note that these values are not encrypted.

## Publish a new release

```bash
Expand Down
2 changes: 2 additions & 0 deletions examples/defender-test-project/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ resources:
trigger:
type: 'webhook'
paused: false
environment-variables:
hello: 'world!'
action-example-4: '516dfd2f-9715-47d4-bcdf-d1f9a7b4d80d'

policies:
Expand Down
17 changes: 11 additions & 6 deletions src/cmd/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,21 +958,23 @@ export default class DefenderDeploy {
encodedZippedCode: code,
});
const { codeDigest } = await client.get(match.actionId);
const environmentVariables = await client.getEnvironmentVariables(match.actionId);

const isSchedule = (
o: DefenderWebhookTrigger | DefenderScheduleTrigger | DefenderMonitorTrigger | DefenderMonitorFilterTrigger,
): o is DefenderScheduleTrigger => o.type === 'schedule';

const mappedMatch = {
name: match.name,
trigger: {
'name': match.name,
'trigger': {
type: match.trigger.type,
frequency: (isSchedule(match.trigger) && match.trigger.frequencyMinutes) || undefined,
cron: (isSchedule(match.trigger) && match.trigger.cron) || undefined,
},
paused: match.paused,
relayerId: match.relayerId,
codeDigest: match.codeDigest,
'paused': match.paused,
'relayerId': match.relayerId,
'codeDigest': match.codeDigest,
'environment-variables': environmentVariables,
};

if (
Expand Down Expand Up @@ -1006,12 +1008,14 @@ export default class DefenderDeploy {
relayerId: maybeRelayer?.relayerId,
});

await client.updateEnvironmentVariables(match.actionId, { variables: action['environment-variables'] ?? {} });

if (newDigest === codeDigest) {
return {
name: match.stackResourceId!,
id: match.actionId,
success: true,
notice: `Skipped code upload - no changes detected for ${match.stackResourceId}`,
notice: `Skipped code upload - no code changes detected for ${match.stackResourceId}`,
response: updatesAction,
};
} else {
Expand Down Expand Up @@ -1050,6 +1054,7 @@ export default class DefenderDeploy {
paused: action.paused,
relayerId: maybeRelayer?.relayerId,
stackResourceId: stackResourceId,
environmentVariables: action['environment-variables'],
});
return {
name: stackResourceId,
Expand Down
3 changes: 2 additions & 1 deletion src/types/docs-schemas/definitions.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,8 @@
"else": {},
"required": ["type"]
},
"paused": { "type": "boolean" }
"paused": { "type": "boolean" },
"environment-variables": { "type": "object", "additionalProperties": { "type": "string" } }
},
"required": ["name", "path", "trigger", "paused"]
},
Expand Down
2 changes: 2 additions & 0 deletions src/types/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@

* [Untitled object in Definitions](./definitions-definitions-relayer-properties-addressfromrelayer-anyof-0.md) – `definitions.schema.json#/definitions/relayer/properties/address-from-relayer/anyOf/0`

* [Untitled object in Definitions](./definitions-definitions-action-properties-environment-variables.md) – `definitions.schema.json#/definitions/action/properties/environment-variables`

* [UrlConfig](./definitions-definitions-urlconfig.md) – `definitions.schema.json#/definitions/urlConfig`

### Arrays
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## additionalProperties Type

`string`
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## environment-variables Type

`object` ([Details](definitions-definitions-action-properties-environment-variables.md))

# environment-variables Properties

| Property | Type | Required | Nullable | Defined by |
| :-------------------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Additional Properties | `string` | Optional | cannot be null | [Definitions](definitions-definitions-action-properties-environment-variables-additionalproperties.md "definitions.schema.json#/definitions/action/properties/environment-variables/additionalProperties") |

## Additional Properties

Additional properties are allowed, as long as they follow this schema:



* is optional

* Type: `string`

* cannot be null

* defined in: [Definitions](definitions-definitions-action-properties-environment-variables-additionalproperties.md "definitions.schema.json#/definitions/action/properties/environment-variables/additionalProperties")

### additionalProperties Type

`string`
33 changes: 26 additions & 7 deletions src/types/docs/definitions-definitions-action.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

# action Properties

| Property | Type | Required | Nullable | Defined by |
| :------------------ | :-------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------- |
| [name](#name) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-name.md "definitions.schema.json#/definitions/action/properties/name") |
| [path](#path) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-path.md "definitions.schema.json#/definitions/action/properties/path") |
| [relayer](#relayer) | Merged | Optional | cannot be null | [Definitions](definitions-definitions-relayerordefenderid.md "definitions.schema.json#/definitions/action/properties/relayer") |
| [trigger](#trigger) | `object` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-trigger.md "definitions.schema.json#/definitions/action/properties/trigger") |
| [paused](#paused) | `boolean` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-paused.md "definitions.schema.json#/definitions/action/properties/paused") |
| Property | Type | Required | Nullable | Defined by |
| :---------------------------------------------- | :-------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [name](#name) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-name.md "definitions.schema.json#/definitions/action/properties/name") |
| [path](#path) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-path.md "definitions.schema.json#/definitions/action/properties/path") |
| [relayer](#relayer) | Merged | Optional | cannot be null | [Definitions](definitions-definitions-relayerordefenderid.md "definitions.schema.json#/definitions/action/properties/relayer") |
| [trigger](#trigger) | `object` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-trigger.md "definitions.schema.json#/definitions/action/properties/trigger") |
| [paused](#paused) | `boolean` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-paused.md "definitions.schema.json#/definitions/action/properties/paused") |
| [environment-variables](#environment-variables) | `object` | Optional | cannot be null | [Definitions](definitions-definitions-action-properties-environment-variables.md "definitions.schema.json#/definitions/action/properties/environment-variables") |

## name

Expand Down Expand Up @@ -111,3 +112,21 @@ any of
### paused Type

`boolean`

## environment-variables



`environment-variables`

* is optional

* Type: `object` ([Details](definitions-definitions-action-properties-environment-variables.md))

* cannot be null

* defined in: [Definitions](definitions-definitions-action-properties-environment-variables.md "definitions.schema.json#/definitions/action/properties/environment-variables")

### environment-variables Type

`object` ([Details](definitions-definitions-action-properties-environment-variables.md))
33 changes: 26 additions & 7 deletions src/types/docs/definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2368,13 +2368,14 @@ Reference this group by using
{"$ref":"definitions.schema.json#/definitions/action"}
```

| Property | Type | Required | Nullable | Defined by |
| :------------------ | :-------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |
| [name](#name-6) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-name.md "definitions.schema.json#/definitions/action/properties/name") |
| [path](#path) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-path.md "definitions.schema.json#/definitions/action/properties/path") |
| [relayer](#relayer) | Merged | Optional | cannot be null | [Definitions](definitions-definitions-action-properties-relayerordefenderid.md "definitions.schema.json#/definitions/action/properties/relayer") |
| [trigger](#trigger) | `object` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-trigger.md "definitions.schema.json#/definitions/action/properties/trigger") |
| [paused](#paused-3) | `boolean` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-paused.md "definitions.schema.json#/definitions/action/properties/paused") |
| Property | Type | Required | Nullable | Defined by |
| :---------------------------------------------- | :-------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [name](#name-6) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-name.md "definitions.schema.json#/definitions/action/properties/name") |
| [path](#path) | `string` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-path.md "definitions.schema.json#/definitions/action/properties/path") |
| [relayer](#relayer) | Merged | Optional | cannot be null | [Definitions](definitions-definitions-action-properties-relayerordefenderid.md "definitions.schema.json#/definitions/action/properties/relayer") |
| [trigger](#trigger) | `object` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-trigger.md "definitions.schema.json#/definitions/action/properties/trigger") |
| [paused](#paused-3) | `boolean` | Required | cannot be null | [Definitions](definitions-definitions-action-properties-paused.md "definitions.schema.json#/definitions/action/properties/paused") |
| [environment-variables](#environment-variables) | `object` | Optional | cannot be null | [Definitions](definitions-definitions-action-properties-environment-variables.md "definitions.schema.json#/definitions/action/properties/environment-variables") |

### name

Expand Down Expand Up @@ -2476,6 +2477,24 @@ any of

`boolean`

### environment-variables



`environment-variables`

* is optional

* Type: `object` ([Details](definitions-definitions-action-properties-environment-variables.md))

* cannot be null

* defined in: [Definitions](definitions-definitions-action-properties-environment-variables.md "definitions.schema.json#/definitions/action/properties/environment-variables")

#### environment-variables Type

`object` ([Details](definitions-definitions-action-properties-environment-variables.md))

## Definitions group block-explorer-api-key

Reference this group by using
Expand Down
Loading