# auth0-m2m

Lambdas for managing machine-to-machine (M2M) clients in Auth0.

## Setup
* Install [docker](https://docs.docker.com/get-docker/)
* Clone this repository
* Navigate to the lambda you want to work on in `lambda/`

## Deployment
This repository uses Jenkinsfile to manage its CI/CD pipeline. There are a few
nuances to be aware of when ensuring successful deployment of a lambda function:

### Adding a new Lambda function
Let's say you are adding a new Lambda function `my_new_lambda`. For QA, it needs to be deployed to permissions-platform-qa and qa (account id 437795906767) . For Prod, it needs to be deployed ot only permissions-platform-prod.

1. In Jenkinsfile, update the `FUNCTIONS` list
2. The key should be the function's name (in snake_case)
3. Specify the lambda's directory using `dir`
4. Maintain a separate list for `qaAccounts` and `prodAccounts`.

You would end up adding something  like this:

```groovy
'my_new_lambda': [
        dir: 'lambda/my_new_lambda',
        qaAccounts: ['permissions-platform-qa', 'qa'],
        prodAccounts: ['permissions-platform-prod']
    ]
```

#### Isolated Integration Tests for the Lambda Function

Suppose you want to test the Lambda Function in AWS, proper. You can add `isolatedIntegrationTest` to the `FUNCTIONS` list:

```groovy
'my_new_lambda': [
        dir: 'lambda/my_new_lambda',
        ...,
        isolatedIntegrationTest: [
            account: 'orcd-permissions-platform-qa',
            environment: 'test',
            testRole: 'test-my-new-lambda-integration-test-role'
        ]
    ]
```

* `account` should indicate with AWS Account the lambda function should be deployed to.
* `environment` indicates the namespacing used for the isolated lambda function.
* `testRole` indicates the AWS IAM Role that Jenkins should assume in the AWS Account, to run integration test. This role should be created using `terraform-infra` and attached with the appropriate IAM policies for the integration test.

When `isolatedIntegrationTest` is present, the Jenkinsfile will deploy to the lambda function, and then run `make ci_test_integration` from the lambda function's directory.

### Supporting a new AWS Account
Let's say you are deploying a Lambda function to a new AWS Account.

1. In Jenkinsfile, update the `AWS_ACCOUNTS` list
2. The key should be the [AWS Account's commonly used name](https://github.com/theorchard/terraform-aws-accounts-map/blob/master/main.tf)
3. Specify the `accountId` and `deploymentRole` (which should be standardized to `<env>-jenkins-pipeline-deploy-role`).

You would end up adding something like this:

```groovy
    'orcd-abacus-qa': [
        accountId     : '989790945997',
        deploymentRole: 'qa-jenkins-pipeline-deploy-role'
    ]
```

4. In Jenkinfile, update the `FUNCTIONS` list to include the added key for the AWS Account (see above).


## Running

### Start Container

```sh
make up
```

### Execute Function
Use the HTTP client of your choice. The body of the request is the `event` passed into the function.

```sh
make test_event
```

or to use a different event:

```sh
curl --request POST \
  --url http://localhost:9000/2015-03-31/functions/function/invocations \
  --header 'Content-Type: application/json' \
  --data-binary "@your_desired_event.json"
```

### Load Changes
The `src` directory and `config.py` are mounted into the container via the `docker-compose.yaml` volumes configuration. This means you don't need to re-build the entire container to see changes. **However** the container will need to be restarted. This process should be as quick as restarting uwsgi when making changes to a web application.

```sh
make restart
```
:zap: You should add this command to a post-write hook in your preferred editor to automatically restart.

### Deploy to Dev

If you would like to deploy your lambda to the AWS Dev environment before pushing to AWS ECR make sure that the Docker image is built for the proper platform (especially if you are using M1 chip).
So instead of
```shell
$ docker build -t my-lambda .
```
do
```shell
$ docker build -t my-lambda --platform=linux/amd64 .
```

## Linting and Testing

### Run Container

```sh
make test_unit
```

### Set pytest Options
Sometimes you may want to customize how tests run using [pytest options](https://docs.pytest.org/en/stable/usage.html) when doing development locally, only running a subset of tests using `-k` for example. Simply edit `TEST_ARGS` value in `docker-compose.yaml`, **without** quotes, to set the options you need.

:warning: Commited changes will modify how the build pipeline runs tests

### Set pytest-cov Options
By default test coverage is calculated for files in `./src` and displayed in a table after tests run.
* If you want to see a detailed output, edit `COV_REPORT` value in `docker-compose.yaml` to be `html` and visit `http://localhost:8000/`
* If you want to turn off coverage report generation, edit `COV_REPORT` value in `docker-compose.yaml` to be `off`

:warning: Commited changes will modify how the build pipeline runs tests, **do not** commit `COV_REPORT=html`

### Skip Linting
When developing locally, you might not want to worry about linting when working to make tests pass. Simple edit the `SKIP_LINT` value in `docker-compose.yaml` to be `1`.

:warning: Careful not to commit changes unless you **really** want to not run linting on the build pipeline

### Capture Exit Code
Unless the container itself crashes, or is killed, the exit code will be `0`. When the exit code of `lint-and-test.sh` script matters, a pull-request builder for example, run tests with the following flags.
```
$ docker compose up --exit-code-from lint-and-test --abort-on-container-exit --build lint-and-test
```
### Datadog Configuration

In order to get traces and metrics (in addition to logs) from the [Datadog Lambda Library](https://docs.datadoghq.com/serverless/installation/python/?tab=containerimage), you'll need to have the following environment variables:
    ENVIRONMENT
    DD_LAMBDA_HANDLER (your lambda's original handler, e.g. "src.app.handler")
These can be set via terraform, for example [here](https://github.com/theorchard/terraform-infra/blob/master/qa/lambda-sound-recordings/lambda_sr_add_version.tf#L84-L91).
Notice, the linked example in terraform-infra is utilizing our terraform-lambda module, which does a lot of the setup work under the hood.
