# Enabling AWS resources
> This bundle contains all pages in the Enabling AWS resources section.
> Source: https://www.union.ai/docs/v2/union/deployment/byoc/enabling-aws-resources/

=== PAGE: https://www.union.ai/docs/v2/union/deployment/byoc/enabling-aws-resources ===

# Enabling AWS resources

> **📝 Note**
>
> An LLM-optimized bundle of this entire section is available at [`section.md`](https://www.union.ai/docs/v2/union/deployment/byoc/section.md).
> This single file contains all pages in this section, optimized for AI coding agent context.

Components of your Union.ai data plane will need to connect to and communicate with other resources in your cloud environment such as **BYOC deployment > Enabling AWS resources > Enabling AWS S3**, **BYOC deployment > Enabling AWS resources > Enabling AWS ECR**, and so forth.

> [!NOTE] Secret management
> We strongly recommend using the [Union.ai secrets manager](https://www.union.ai/docs/v2/union/user-guide/task-configuration/secrets/page.md) to manage secrets rather than AWS Secrets Manager. If your organization must use AWS Secrets Manager, however, see **BYOC deployment > Enabling AWS resources > Enabling AWS Secrets Manager**.

As much as possible, access to the resources you need will be pre-configured by the Union.ai team when they set up your data plane.
For example, if you want your task code to have access to a specific S3 bucket or database, this can be pre-configured.
**You just have to inform the team of your specific requirements before the setup process begins**.

As your projects evolve, your needs may change.
You can always contact the Union.ai team for help enabling additional resources as required.

**There are also some cases where you may want to configure things on your own.**
**Below we give a general overview of these self-configuration options.**
**The sub-pages of this section give examples for specific resources.**

## Types of access

Broadly speaking, there are two categories of access that you are likely to have to deal with:

* **Infrastructure access**:
  Enabling access to a resource for your data plane infrastructure.
  The most common case occurs when you are using **BYOC deployment > Enabling AWS resources > Enabling AWS ECR** for your task container images, and it resides in an AWS account other than the one containing your data plane.
  In that case, some configuration is required to enable the Union.ai operator on your data plane to pull images from the registry when registering your workflows and tasks.
  **If you are using an ECR instance within the same AWS account as your data plane, then access is enabled by default and no further configuration is needed.**
* **Task code access**:
  Enabling access to a resource for your task code.
  For example, your task code might need to access **BYOC deployment > Enabling AWS resources > Enabling AWS S3** or **BYOC deployment > Enabling AWS resources > Enabling AWS Secrets Manager** at runtime.
  This involves granting permission to roles that are attached to the Kubernetes cluster within which your task code runs.

## Infrastructure-level access

The only infrastructure-level access issue you are likely to encounter is around access to an AWS Elastic Container Registry (ECR) _in an AWS account other than the one in which your data plane resides_.

**If your task container images are stored in an AWS Elastic Container Registry in the same AWS account as your data plane, then access is already enabled. You do not have to do anything.**

If your task container images reside in an ECR instance in **another AWS account** you will need configure that ECR instance to allow access from your data plane.
See **BYOC deployment > Enabling AWS resources > Enabling AWS ECR** for details.

## Task code access

When your task code runs, it executes within a pod in the Kubernetes cluster in your data plane.
To enable your task code to access cloud resources you must grant the appropriate permissions to a role that is attached to the Kubernetes cluster.

There are two main options for setting this up:

* **Project-domain-scoped access**: With this arrangement, you define the permissions you want to grant to your task code, and those permissions are applied only to specific project-domain pairs.
* **Global access**: With this arrangement, you define the permissions you want to grant to your task code, and those permissions are then applied to code in all your projects and domains.

Global access is recommended for most use cases since it is simpler, but if you have a compelling reason to restrict access, then the project-domain-scoped access is available, at the cost of some additional complexity in setup.

> [!NOTE] Relationship with RBAC
> The permissions being discussed here are attached to a project and domain.
> This is independent of the permissions granted to users and machine applications through Union.ai's role-based access control (see the user management documentation).
> But, the two types of permissions are related.
>
> For example, for a user (or machine application) to have read access to an S3 bucket, two things are required:
>
> * The user (or machine application) must have **execute** permission for the project and domain where the code that does the reading resides.
> * The project and domain must have read permission for the S3 bucket.

## Background

As you know, your workflows and tasks run in a Kubernetes cluster within your data plane.
Within that cluster, the Kubernetes pods allocated to run your task code are organized as follows:

* The set of task pods is partitioned into namespaces where each namespace corresponds to a project-domain pair.
* All workflows running in a given project and domain are run on pods within that namespace.
  For example, code in the `development` domain of project `foo` runs in the namespace `foo-development` while code in the `staging` domain of project `bar` runs in the namespace `bar-staging`, and so forth.
* By default, all project-domain namespaces are bound to a common IAM role which we will refer to as `<UserFlyteRole>`.
  Its actual name differs from organization to organization. **The actual name will have the form `<YourOrgPrefix>-userflyterole`**.
* The role `<UserFlyteRole>` has an attached policy called `userflyterole`.
  This policy contains all the permissions granted to your task code when your data plane was set up.
  If you requested permissions for resources specific to your organization at set up time, they will have been added here.

> [!NOTE] `<UserFlyteRole>` vs `userflyterole`
> The entity that we refer to here as `<UserFlyteRole>` is an IAM role.
> As mentioned the actual name of this role in your system will be of the form `<YourOrgPrefix>-userflyterole.`
>
> By default, this role has an attached IAM policy called `userflyterole`.
> This is the literal name used in all AWS-based data planes.
>
> **Be aware of the difference and don't get these two things confused!**

> [!NOTE] `<UserFlyteRole>`vs `<AdminFlyteRole>`
> In addition to the task pods, your cluster also contains pods that run Union.ai services, which are used to manage tasks and to connect your cluster to the control plane.
> These pods are bound to a different default role, `<AdminFlyteRole>` (again, its actual name differs from organization to organization).
> The separation of this role from `<UserFlyteRole>` serves to provide isolation between Union.ai administrative logic and your workflow logic.
>
> **You should not alter any settings associated with `<AdminFlyteRole>`**.

## Enabling access

To enable your task code to access a resource:

* **BYOC deployment > Enabling AWS resources > Enabling access > Creating a custom policy** that grants the appropriate permissions for your resource.
  This is the step where you define exactly which permissions you want to grant (read-only, read/write, list, etc.).
  The name of this policy is yours to determine.
  Here we will refer to it as `<CustomPolicy>`.

You can then choose whether to enable **global access** or **project-domain-scoped access**:

* **BYOC deployment > Enabling AWS resources > Enabling access > Setting up global access** to the resource, you simply attach `<CustomPolicy>` to the existing `<UserFlyteRole>`.
* **BYOC deployment > Enabling AWS resources > Enabling access > Setting up project-domain-scoped access** to your resource:
  * Create your own custom role (let's refer to it `<CustomRole>`)
  * Attach `<CustomPolicy>` to `<CustomRole>`.
  * Also, attach the policy called `userflyterole` to `<CustomRole>` (this will ensure that `<CustomRole>` has all the default permissions needed to allow tasks to run).
  * Attach `<CustomRole>` to the desired project-domain namespace.

![](../../../_static/images/user-guide/integrations/enabling-aws-resources/union-roles.png)

### Creating a custom policy

Regardless of which route you take (global vs project-domain-scoped) the first step is to create a policy that grants the desired permissions to your resource.

To create a new policy:

* Go to **IAM > Access management > Policies**.
* Select **Create policy**.
* Go through the sections of the visual editor to define the permissions you wish to grant.
  * Alternatively, you can paste a JSON definition directly into the JSON editor.
  * The details of what permissions to grant depend on the resource in question and the access you wish to grant.
    Specific examples are covered in **BYOC deployment > Enabling AWS resources > Enabling AWS S3** and **BYOC deployment > Enabling AWS resources > Enabling AWS Secrets Manager**.
* Proceed through the steps of the wizard, give your policy a name (which we will call `<CustomPolicy>`), and select **Create policy**.
* Record the name and ARN of your policy.
  Here we will refer to the ARN is `<CustomPolicyArn>`.

### Setting up global access

To set up global access, you must bind the `<CustomPolicy>` that you created above to the role `<UserFlyteRole>`.

> [!NOTE]
> As mentioned above, the actual name of `<UserFlyteRole>` has the form:
>
> **`<YourOrgPrefix>-userflyterole`**
>
> You should be able to find the role by searching in your AWS IAM console for roles with names that follow that pattern.

* Go to **IAM > Access management > Roles**.
* Find `<UserFlyteRole>` and select the checkbox beside it.
* In the **Add Permissions** drop-down menu, select **Attach Policies**.
* In the displayed list find `<CustomPolicy>` and select its checkbox, then select **Add permissions**.

> [!NOTE]
> Alternatively, you can perform the binding from the command line like this:
>
> ```bash
> $ aws iam attach-role-policy \
>  --policy-arn <CustomPolicyArn> \
>  --role-name <UserFlyteRole>
> ```
>
> Notice that in this case, you have to use `<CustomPolicyArn>` here instead of `<CustomPolicy>`.

**At this point, all task code in your organization will have access to the cloud resource as defined by your custom policy.**

### Setting up project-domain-scoped access

To set up project-domain-scoped access, you do this:

In AWS:

* Create the IAM role, `<CustomRole>`.
* Add the `userflyterole` policy to `<CustomRole>`.
* Add `<CustomPolicy>` to `<CustomRole>`.

In Union.ai (using `uctl`):

* Bind `<CustomRole>` to the project-domain pair desired.

### Create the IAM role

1. Sign in to the AWS Management Console as an administrator of your account, and open the IAM console.
2. In the navigation pane, choose **Roles** and then choose **Create role**.
3. Choose the **Web identity** role type.
4. In the **Identity provider** dropdown select `oidc.eks.<Suffix>.`Record this name.
5. Choose `sts.amazonaws.com` as the **Audience** and select **Next**.
6. On the **Add permissions** page, search for the `userflyterole` policy and check the box beside it and select **Next**.
7. Enter a name and description for this role.
8. Under **Step 1: Select trusted entities**, click edit and _replace_ the `Condition` block with the following, where `oidc.eks.<Suffix>` is the value from step 4, and `<Project>`, and `<Domain>` are the Union.ai project and domain pairs you want to set custom permissions for. Repeat for each project-domain pair.

```json
"Condition": {
    "StringEquals": {
        "oidc.eks.<Suffix>:sub": [
            "system:serviceaccount:<Project>-<Domain1>:default",
            "system:serviceaccount:<Project>-<Domain2>:default"
        ]
    }
}
```

9. Add additional permissions as needed, following [these steps](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html).
10. Select **Create role**.
11. In the **Summary** section of the new role's details pane, note the ARN value.

### Configure the cluster to use the new IAM role

Repeat the following steps for each project-domain pair:

1.  Create a file named `cluster_resource_attributes.yaml` with the following contents:

```yaml
attributes:
defaultUserRoleValue: <ARN from step 11 above>
domain: <domain>
project: <project>
```

2.  Run the following command to override the IAM role used for Union.ai Tasks in this Project-Domain:

```bash
uctl update cluster-resource-attribute --attrFile cluster_resource_attributes.yaml
```

3.  You can verify the overrides by running:

```bash
uctl get cluster-resource-attribute -p <project> -d <domain>
```

**At this point, only code in your chosen project-domain pairs will have access to the cloud resource as defined by your custom policy.**

=== PAGE: https://www.union.ai/docs/v2/union/deployment/byoc/enabling-aws-resources/enabling-aws-s3 ===

# Enabling AWS S3

For Union.ai customers whose data plane is in AWS, we walk through setting up access to your own AWS S3 bucket.

> [!NOTE] AWS S3 in the Union.ai environment
> Your data plane is set up with a Kubernetes cluster and other resources.
> Among these are a number of S3 buckets used internally by the Union.ai operator running in the cluster (see [Platform architecture](https://www.union.ai/docs/v2/union/deployment/byoc/platform-architecture)) to store things like workflow metadata.
>
> **These **_**are not**_** the S3 bucket we are talking about in this section.**
>
> **We are discussing the case where you have **_**your own S3 bucket**_** that you set up to store input and output data used by your workflows.**

## Add permissions to your custom policy

In order to enable access to an AWS resource (in this case S3) you need to create a custom policy in AWS IAM with the required permissions and attach it to either the existing _User Flyte Role_ associated with your data plane Kubernetes cluster or to a custom role which you have created and attached to the cluster.
The general procedure is covered in **BYOC deployment > Enabling AWS resources > Enabling AWS S3**.

_In order to enable S3 access in particular, in the step_ [#add-permissions-to-your-custom-policy](./enabling-aws-s3#add-permissions-to-your-custom-policy) _you must specify the needed permissions. For example:_

- `s3:ListBucket` - This permission allows you to list the objects in the bucket.
- `s3:GetObject` - This permission allows you to retrieve objects from the bucket.
- `s3:PutObject` - This permission allows you to upload objects to the bucket.

Here is a sample JSON policy document that grants these permissions:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowReadWriteBucket",
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::<BucketName>/*",
        "arn:aws:s3:::<BucketName>"
      ]
    }
  ]
}
```

In the `Resource` field, replace `<BucketName>` with the actual name of your S3 bucket.

## Accessing S3 from your task code

Once you have enabled access to your S3 bucket, you can use the standard [AWS SDK for Python (Boto3)](https://aws.amazon.com/sdk-for-python/) in your task code to read and write to it.

=== PAGE: https://www.union.ai/docs/v2/union/deployment/byoc/enabling-aws-resources/enabling-aws-ecr ===

# Enabling AWS ECR

## Access to ECR in the same account is enabled by default

When registering tasks and workflows, the Union.ai infrastructure in your data plane must have access to the container registry that holds the task container images you will be using.
If your data plane is on AWS then you may want to use AWS Elastic Container Registry (ECR) to store these images.

For details on how to use ECR when building and deploying your workflows, see the ImageSpec with ECR documentation.

**In most cases, you will be using an ECR instance in the same AWS account as your data plane.**
**If this is the case, then you do not need to configure anything.**
**Access to ECR in the same account is enabled by default.**

## Enabling cross-account access to ECR

If you want to store your task container images in an ECR instance in an AWS account _other than the one that holds your data plane_, then you will have to configure that ECR instance to permit access from your data plane.
Here are the details:

* Your Union.ai data plane comes pre-configured with a specific role, which we will refer to here as `<FlyteWorkerNodeGroupRole>`.
* The actual name of this role depends on your organization's name. It will be of the form `unionai-<YourOrganizationName>-flyteworker-node-group`.

To enable access to the ECR instance in the other account, do the following:

* In your data plane AWS account, Go to **IAM > Roles**.
Find the role `<FlyteWorkerNodeGroupRole>` and copy the ARN of that role.
We will call this `<FlyteWorkerNodeGroupRoleARN>`.
* In the other AWS account (the one that contains the ECR instance), go to **Amazon ECR > Repositories**,
* Find the ECR repository you want to enable and under **Permissions**, select **Edit,** then **Add Statement**.
* Specify the `<FlyteWorkerNodeGroupRoleARN>` as a **Principal** and add (at least) the following permissions:
  * `ecr:BatchCheckLayerAvailability`: This permission allows your data plane to check the availability of image layers in the registry.
  * `ecr:GetDownloadUrlForLayer`: This permission allows your data plane to retrieve a pre-signed URL that is required to download the image layers.
  * `ecr:BatchGetImage`: This permission allows your data plane to retrieve image manifests and image layer information from the registry.
* To specify the above parameters via JSON, select **Edit policy JSON** and use the following policy document:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPull",
      "Effect": "Allow",
      "Principal": {
        "AWS": "<FlyteWorkerNodeGroupRoleARN>"
      },
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability"
      ]
    }
  ]
}
```

* Select **Save**.

Your Union.ai data plane infrastructure should now be able to pull images from the ECR instance. For more information see [How can I allow a secondary account to push or pull images in my Amazon ECR image repository?](https://repost.aws/knowledge-center/secondary-account-access-ecr)

=== PAGE: https://www.union.ai/docs/v2/union/deployment/byoc/enabling-aws-resources/enabling-aws-secrets-manager ===

# Enabling AWS Secrets Manager

> [!NOTE]
> This documentation is for customers who must use AWS Secrets Manager for organizational reasons. For everyone else, we strongly recommend using the
> [Union.ai secrets manager](https://www.union.ai/docs/v2/union/user-guide/task-configuration/secrets) to manage secrets rather than AWS Secrets Manager.

To enable your code to access secrets from AWS Secrets Manager you will need to

* Make sure AWS Secrets Manager is enabled.
* Create your secrets in AWS Secrets Manager.
* Create an AWS policy granting access to your secrets.
* Bind that policy to the User Flyte Role in your Union.ai data plane.
* Retrieve your secrets from within your workflow code.

## Ensure that AWS Secrets Manager is enabled

The first step is to make sure that AWS Secrets Manager is enabled in your AWS environment.
Contact the Union.ai team if you are unsure.

## Create your secrets

> [!NOTE]
> Secrets must be defined within the same region as your Union.ai data plane.
> For example, if your Union.ai data plane is located in `us-west-2`, ensure that the secrets are also in `us-west-2`.

Create your secrets in **AWS Secrets Manager** (see the [AWS documentation](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html) for details):

* Go to **AWS Secrets Manager**.
* Select **Store a new secret**.
* Under **Choose Secret type**:
  * Select **Other type of secret**.
  * Select **Plaintext** (**Key/value** is not supported).
  * Enter your **secret value**.
  * For **Encryption key,** leave the default setting: `aws/secretmanager`.
  * Select **Next**.
* Under **Configure secret**:
  * For **Secret name**, enter a string (this string will form part of the `SECRET_KEY` that you will use to access your secret from within your code).
  * Select **Next**.
* Under **Configure rotation** adjust the settings if needed, or skip the section if not. Then select **Next**.
* Under **Review** check that everything is correct and then select **Store**.

## Get the secret ARN

Once you have created a secret, navigate to **AWS Secrets Manager > Secrets** and select the secret you just created.
From there select **Secret ARN** and record the ARN.
Do this for each secret that you create.

A secret ARN looks like this:

```bash
arn:aws:secretsmanager:<Region>:<AccountId>:secret:<SecretName>-<SixRandomCharacters>
```

> [!NOTE]
> You will need your secret ARN when you access your secret from within your code.
> Specifically, you will need to divide it into two strings:
>
> * **`SECRET_GROUP`**: The part of the ARN up to and including `:secret:`
> Above, it is `arn:aws:secretsmanager:<Region>:<AccountId>:secret:`.
>
> * **`SECRET_KEY`**: The part of the ARN after `:secret:`
> Above, it is `<SecretName>-<SixRandomCharacters>`.
>
> See [Using AWS secrets in your code](./enabling-aws-secrets-manager#using-aws-secrets-in-your-task-code) for details on how these are used.

## Create a policy providing access to your secrets

To provide access to your newly created secrets in your code, you will first need to create a policy that grants read access to those secrets:

* Go to **IAM > Access management > Policies**.
* Select **Create Policy**.
* Open the **JSON** tab and paste in the following definition:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:*"
    }
  ]
}
```

> [!NOTE]
> The`Resource`entry takes a wildcard string that must match the ARNs of the secrets in your environment that you want to grant access to.
> This can be all the secrets in your environment (as shown above) or some subset (achieved by making the wildcard match more specific).
> Be sure to substitute the appropriate`<Region>`and`<AccountNumber>`.

* Select **Next: Tags** and add tags if you wish.
* Select **Next: Review** and enter a **Name** for the policy
* Select **Create Policy**.
* Find your newly created policy in the policy list that comes up next and select it.
* Record the **Policy Name** and **Policy ARN** of your newly created policy.
It should be at the top of the policy summary page.
We will refer to the name as `<SecretManagerPolicyName>` and the ARN as `<SecretManagerPolicyArn>`.

> [!NOTE]
> Alternatively, you can create the policy from the command line like this (remember to substitute the`<Region>`and`<AccountId>`appropriately):
>
> ```bash
> $ aws iam create-policy \
>       --policy-name <YourPolicyName> \
>       --policy-document \
>       { \
>         "Version": "2012-10-17", \
>         "Statement": [ \
>           { \
>             "Effect": "Allow", \
>             "Action": "secretsmanager:GetSecretValue", \
>             "Resource": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:*" \
>           } \
>         ]\
>       }
> ```

## Bind the policy to the User Flyte Role

To grant your code the permissions defined in the policy above, you must bind that policy to the `<UserFlyteRole>` used in your Union.ai data plane.
The precise name of this role differs by organization.
You will need this name as well as the ARN of the policy (`<SecretManagerPolicyArn>`, above) to perform the binding.
See **BYOC deployment > Enabling AWS resources > Enabling AWS Secrets Manager** for directions. Once the binding is done, your secrets are now accessible from within your Flyte code.

## Using AWS secrets in your task code

To use an AWS secret in your task code, do the following:

* Define a `Secret` class using the `SECRET_GROUP` and `SECRET_KEY` derived from the secret ARN, above, and pass it in the `secret_requests` parameter of the `@union.task` decorator.
* Inside the task code, retrieve the value of the secret with a call to\
  `union.current_context().secrets.get(SECRET_GROUP, SECRET_KEY)`.

Here is an example:

```python
import union

SECRET_GROUP = "arn:aws:secretsmanager:<Region>:<AccountId>:secret:"
SECRET_KEY = "<SecretName>-<SixRandomCharacters>"
SECRET_REQUEST = union.Secret(
  group=SECRET_GROUP,
  key=SECRET_KEY,
  mount_requirement=union.Secret.MountType.FILE
)

@union.task(secret_requests=[SECRET_REQUEST])
def t1():
    secret_val = union.current_context().secrets.get(
        SECRET_GROUP,
        group_version=SECRET_GROUP_VERSION
    )
    # do something with the secret. For example, communication with an external API.
    ...
```

> [!WARNING]
> Do not return secret values from tasks, as this will expose secrets to the control plane.

