# Snowflake UDF example to trigger Immuta API calls

## Implementation Workflow

1. Create a lambda function on AWS Lambda
2. Create REST API endpoint on AWS API Gateway
3. Create AWS IAM role for Snowflake connectivity
4. (optional) Validate and associate API Gateway to AWS Lambda function for above steps
5. Create Snowflake integration object
6. Create Snowflake external function
7. Trigger the external function from within Snowflake

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FyxQDiZ2NAMCfRYeVOS7f%2Fimage-20230425-212053.png?alt=media&#x26;token=2ee94c2b-db57-410c-9308-18d551c8eb15" alt=""><figcaption></figcaption></figure>

The following steps creates a UDF and performs a project-context switching/reset back to No Current Project on Immuta if the user has previously set a different project. It is triggered within Snowflake by passing two parameters: user\_api\_key and user\_email\_uid. The UDF is based on a Snowflake integration object’s AWS API gateway info and triggers an AWS Lambda function to perform the API call to Immuta using the provided user\_api\_key and user\_email\_uid. Additionally, this approach allows for other Immuta API endpoints to be hit through the same Lambda function.

The following steps create a UDF and perform a project-context switch or reset back to "No Current Project" on Immuta if the user has previously set a different project.  This process is triggered within Snowflake by passing two parameters: `user_api_key` and `user_email_uid`.  The UDF utilizes the AWS API Gateway information of a Snowflake integration object and triggers an AWS Lambda function to make an API call to Immuta using the provided `user_api_key` and `user_email_uid`. This is an example; other Immuta API endpoints can be accessed using a similar approach.

### **Step 1: Create a lambda function on AWS** <a href="#step-1-create-a-lambda-function-on-aws-lambda" id="step-1-create-a-lambda-function-on-aws-lambda"></a>

* Record the name of the Lambda function.
* Set the function payload from the `currentProject` parameter to `None`.
* (**NOTE**) Replace different endpoint and payload as needed to interact with different Immuta endpoints for various functions.

```python
# AWS Lambda function example to reset Immuta project context to 'No Current Project'
import json
import requests

def lambda_handler(event, context):
   # parse Snowflake values
   api_key = event['data'][0][1]
   user_id = event['data'][0][2]
  
   # set api_key for header; hardcode the api_key for certain api calls if users can't access definition
   headers = {
       'Authorization': 'Bearer ' + api_key,
       'Content-Type': 'application/json',
   }

   # setting payload for the endpoint, update for other endpoints
   data = json.dumps({
       "preferences": {
           "sortProjectState": {
               "column": "name",
               "order": "asc",
               "size": 12
           },
           "tabProjectState": 0,
           "tabDataSourceState": 1,
           "currentProject": None
       }
   })
  
   # immuta endpoint and user uid, replace with your Immuta instance URL
   url = 'https://<your immuta instance>.immutacloud.com/bim/iam/immuta/user/' + user_id + '/profile'
  
   method = 'POST'
   response = requests.request(method, url, headers=headers, json=data)


   json_data = json.loads(response.text)
   currentProject = json_data['preferences']['currentProject']
  
   # set value to return to Snowflake 
   value_to_be_returned={'data':[[0,'success']]}
   json_string_to_return = json.dumps({"data": value_to_be_returned})

   return value_to_be_returned
```

### **Step 2: Create REST API endpoint on AWS API Gateway** <a href="#step-2-create-rest-api-endpoint-on-aws-api-gateway" id="step-2-create-rest-api-endpoint-on-aws-api-gateway"></a>

* Create and set api gateway
  * Create Resources with endpoint
  * Create Method, i.e. **POST** method to **set\_project\_null**
  * Associate the Lambda function to the POST request: i.e:  **bc\_set\_project\_null**
  * Deploy API and note the **Invoke URL**

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FqgYZw3TuNXnQFnxZUiux%2Fimage-20230425-212438.png?alt=media&#x26;token=0a3e8f7b-266a-418f-bfcb-911e646d1a74" alt=""><figcaption></figcaption></figure>

### **Step 3**: **Create AWS IAM role for Snowflake connectivity**  <a href="#step-3-create-aws-iam-role-for-snowflake-connectivity" id="step-3-create-aws-iam-role-for-snowflake-connectivity"></a>

* Create IAM and add APIGateway and Lambda access to it
* Note the **ARN** info

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FrBe6JDePU8pDd5ZgR0W2%2Fimage-20230425-212516.png?alt=media&#x26;token=7e1e6c12-bad1-4d03-92a2-1cc0f849a782" alt=""><figcaption></figcaption></figure>

### **Step 4:&#x20;*****(optional)*****&#x20;Validate and associate API Gateway to AWS Lambda function** <a href="#step-4-optional-review-as-needed-validate-and-associate-api-gateway-to-aws-lambda-function-if-above" id="step-4-optional-review-as-needed-validate-and-associate-api-gateway-to-aws-lambda-function-if-above"></a>

* Go to the AWS lambda function and add it to the lambda function as fit.&#x20;

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FHAWOrNCZm1W770WFuEg4%2Fimage-20230425-212554.png?alt=media&#x26;token=ffeaf8bd-2c2e-4577-b85f-eb796c6852c6" alt=""><figcaption></figcaption></figure>

### **Step 5: Create Snowflake integration object** <a href="#step-5-create-snowflake-integration-object" id="step-5-create-snowflake-integration-object"></a>

* Snowflake integration object: provide the AWS IAM role info, and the API-gateway endpoint.

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FuJVyzgcfKkoAWdB4nXBM%2Fimage-20230425-212619.png?alt=media&#x26;token=5ad46cb5-254e-4a25-bd85-221bfa9b2012" alt=""><figcaption></figcaption></figure>

* Describing the Snowflake integration object will provide the `API_AWS_IAM_USE_ARN` and the `API_AWS_EXTERNAL_ID`, which need to be provided to the AWS IAM role on AWS.

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FrNgLAEdxJU4SnUaGtaqp%2Fimage-20230425-212644.png?alt=media&#x26;token=68869547-b717-4c70-9f17-7c8fa7a1d803" alt=""><figcaption></figcaption></figure>

* On **AWS**: navigate to the IAM role add the above information to the **Trust Relationships** for the role:

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FXkti7itzi0WteSMp35fx%2Fimage-20230425-212714.png?alt=media&#x26;token=833de8f0-1984-434e-b28e-694c7b528e19" alt=""><figcaption></figcaption></figure>

### **Step 6: Create Snowflake external function** <a href="#step-6-create-snowflake-external-function" id="step-6-create-snowflake-external-function"></a>

* Create an external function which takes two parameters: api\_key and user\_id(email)
* Associate the function with the integration object and the API Gateway endpoint

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2FXi1jQf5RWBKImqeAsesz%2Fimage-20230425-212731.png?alt=media&#x26;token=d62838a9-bdba-4751-832c-04d13cb3da45" alt=""><figcaption></figcaption></figure>

### **Step 7: Trigger the external function from within Snowflake** <a href="#step-7-calling-triggering-the-external-function-from-within-snowflake" id="step-7-calling-triggering-the-external-function-from-within-snowflake"></a>

* Test the lambda function has been throughly tested before deployment.&#x20;
* Execute a `SELECT` query on the function using the parameter values shown in the image below.
* The project context in the Immuta instance will be reset or set to "**No Current Project.**"

<figure><img src="https://880008646-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FtRt87fFOiAcl7rp095oa%2Fuploads%2F8X5drf1U4pseD4Pkbn65%2Fimage-20230425-212800.png?alt=media&#x26;token=f009ce02-6875-4f75-b7f0-0db5b8c9c109" alt=""><figcaption></figcaption></figure>

&#x20;

[snowflake](https://immuta.atlassian.net/wiki/label/CustomerSuccess/snowflake)[udf](https://immuta.atlassian.net/wiki/label/CustomerSuccess/udf)[aws-lambda](https://immuta.atlassian.net/wiki/label/CustomerSuccess/aws-lambda)[<br>](https://immuta.atlassian.net/wiki/label/CustomerSuccess/external-function)
