|
| 1 | +import { NextSeo } from 'next-seo'; |
| 2 | +import { Callout, Tabs } from 'nextra/components'; |
| 3 | + |
| 4 | +<NextSeo description="Access other AWS services from AWS Lambda by using the built-in AWS credentials." /> |
| 5 | + |
| 6 | +# AWS credentials on AWS Lambda |
| 7 | + |
| 8 | +When your PHP application runs on AWS Lambda, it automatically has access to AWS credentials. This means you don't need to manage AWS access keys or credentials in your code - Lambda handles this for you. |
| 9 | + |
| 10 | +<Callout type="warning"> |
| 11 | + Don't deploy AWS access keys in your Lambda functions or environment variables. Lambda provides credentials automatically. |
| 12 | + |
| 13 | + This is a common mistake **when migrating an existing application to AWS Lambda**. |
| 14 | +</Callout> |
| 15 | + |
| 16 | +## How it works |
| 17 | + |
| 18 | +Lambda functions **automatically get AWS access keys** in their environment variables. These credentials are temporary and managed by AWS, so you don't have to worry about rotating them or keeping them secure. |
| 19 | + |
| 20 | +```php |
| 21 | +echo $_SERVER['AWS_ACCESS_KEY_ID']; // AKIAIOSFODNN7EXAMPLE |
| 22 | +echo $_SERVER['AWS_SECRET_ACCESS_KEY']; // wJalrXUtnFEM |
| 23 | +echo $_SERVER['AWS_SESSION_TOKEN']; // AQoEXAMPLEH4aoAH0gNCAPy... |
| 24 | +``` |
| 25 | + |
| 26 | +The PHP AWS SDK automatically detects and uses them. Here's an example with S3: |
| 27 | + |
| 28 | +```php |
| 29 | +$s3 = new \Aws\S3\S3Client([ |
| 30 | + 'version' => 'latest', |
| 31 | + 'region' => $_SERVER['AWS_REGION'], |
| 32 | + // No credentials needed, the SDK uses the environment variables automatically |
| 33 | +]); |
| 34 | + |
| 35 | +// Use S3 normally |
| 36 | +$result = $s3->putObject([ |
| 37 | + 'Bucket' => 'my-bucket', |
| 38 | + 'Key' => 'file.txt', |
| 39 | + 'Body' => 'Hello from Lambda!' |
| 40 | +]); |
| 41 | + |
| 42 | +// Note that this also works with https://async-aws.com |
| 43 | +``` |
| 44 | + |
| 45 | +Note that **Laravel and Symfony automatically pick up these permissions** too. |
| 46 | + |
| 47 | +These credentials have access controlled by an IAM role defined in `serverless.yml`. |
| 48 | + |
| 49 | +<Callout type="info"> |
| 50 | + By default, Lambda functions **don't have any access** (principle of least privilege). To access other AWS services (like S3 or SQS), you need to add permissions to that IAM role in `serverless.yml` (read below). |
| 51 | +</Callout> |
| 52 | + |
| 53 | +## Adding permissions |
| 54 | + |
| 55 | +To grant your Lambda function access to AWS services, add IAM statements to your `serverless.yml`: |
| 56 | + |
| 57 | +```yaml |
| 58 | +service: my-app |
| 59 | + |
| 60 | +provider: |
| 61 | + name: aws |
| 62 | + iam: |
| 63 | + role: |
| 64 | + statements: |
| 65 | + # IAM statements here... |
| 66 | + |
| 67 | +functions: |
| 68 | + # ... |
| 69 | +``` |
| 70 | + |
| 71 | +### Example: S3 |
| 72 | + |
| 73 | +To read and write files to an S3 bucket: |
| 74 | + |
| 75 | +```yaml |
| 76 | +provider: |
| 77 | + name: aws |
| 78 | + iam: |
| 79 | + role: |
| 80 | + statements: |
| 81 | + # Allow Lambda to read and write to S3 |
| 82 | + - Effect: Allow |
| 83 | + Action: |
| 84 | + - s3:GetObject |
| 85 | + - s3:PutObject |
| 86 | + - s3:DeleteObject |
| 87 | + Resource: arn:aws:s3:::my-bucket/* |
| 88 | + # Allow listing bucket contents |
| 89 | + - Effect: Allow |
| 90 | + Action: s3:ListBucket |
| 91 | + Resource: arn:aws:s3:::my-bucket |
| 92 | +``` |
| 93 | +
|
| 94 | +<Callout> |
| 95 | + If you use the [Lift `storage` construct](./storage.mdx#s3-storage) to create S3 buckets, it [automatically adds the necessary permissions](https://github.com/getlift/lift/blob/master/docs/storage.md#permissions) to your functions. No need to set up permissions manually! |
| 96 | +</Callout> |
| 97 | + |
| 98 | +### Example: SQS |
| 99 | + |
| 100 | +To send and receive messages from SQS queues: |
| 101 | + |
| 102 | +```yaml |
| 103 | +provider: |
| 104 | + name: aws |
| 105 | + iam: |
| 106 | + role: |
| 107 | + statements: |
| 108 | + # Allow Lambda to access an SQS queue |
| 109 | + - Effect: Allow |
| 110 | + Action: |
| 111 | + - sqs:SendMessage |
| 112 | + - sqs:ReceiveMessage |
| 113 | + - sqs:DeleteMessage |
| 114 | + - sqs:GetQueueAttributes |
| 115 | + Resource: arn:aws:sqs:${aws:region}:${aws:accountId}:my-queue |
| 116 | +``` |
| 117 | + |
| 118 | +<Callout> |
| 119 | + If you use the [Lift `queue` construct](../use-cases/sqs.mdx#creating-sqs-queues) to create SQS queues, it [automatically adds the necessary permissions](https://github.com/getlift/lift/blob/master/docs/queue.md#permissions) to your functions. No need to set up permissions manually! |
| 120 | +</Callout> |
| 121 | + |
| 122 | +## Common services and permissions |
| 123 | + |
| 124 | +Here are the IAM actions you'll typically need for common AWS services: |
| 125 | + |
| 126 | +### DynamoDB |
| 127 | +```yaml |
| 128 | +- Effect: Allow |
| 129 | + Action: |
| 130 | + - dynamodb:GetItem |
| 131 | + - dynamodb:PutItem |
| 132 | + - dynamodb:UpdateItem |
| 133 | + - dynamodb:DeleteItem |
| 134 | + - dynamodb:Query |
| 135 | + - dynamodb:Scan |
| 136 | + Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/my-table |
| 137 | +``` |
| 138 | + |
| 139 | +### Secrets Manager |
| 140 | +```yaml |
| 141 | +- Effect: Allow |
| 142 | + Action: secretsmanager:GetSecretValue |
| 143 | + Resource: arn:aws:secretsmanager:${aws:region}:${aws:accountId}:secret:my-secret-* |
| 144 | +``` |
| 145 | + |
| 146 | +### SNS (notifications) |
| 147 | +```yaml |
| 148 | +- Effect: Allow |
| 149 | + Action: sns:Publish |
| 150 | + Resource: arn:aws:sns:${aws:region}:${aws:accountId}:my-topic |
| 151 | +``` |
| 152 | + |
| 153 | +### EventBridge |
| 154 | +```yaml |
| 155 | +- Effect: Allow |
| 156 | + Action: events:PutEvents |
| 157 | + Resource: arn:aws:events:${aws:region}:${aws:accountId}:event-bus/my-event-bus |
| 158 | +``` |
| 159 | + |
| 160 | +### SSM Parameter Store |
| 161 | +```yaml |
| 162 | +- Effect: Allow |
| 163 | + Action: |
| 164 | + - ssm:GetParameter |
| 165 | + - ssm:GetParameters |
| 166 | + Resource: arn:aws:ssm:${aws:region}:${aws:accountId}:parameter/my-app/* |
| 167 | +``` |
| 168 | + |
| 169 | +## Troubleshooting |
| 170 | + |
| 171 | +### Access Denied errors |
| 172 | + |
| 173 | +If you get "Access Denied" errors when trying to use AWS services: |
| 174 | + |
| 175 | +1. Check that you've added the correct IAM permissions in `serverless.yml` |
| 176 | +2. Verify the resource ARN is correct (bucket name, queue name, etc.) |
| 177 | +3. Make sure you've redeployed after adding permissions |
| 178 | +4. [Check the logs](./logs.mdx) for the exact error message |
| 179 | + |
| 180 | +### Testing locally |
| 181 | + |
| 182 | +When testing locally remember that you will need to provide AWS credentials since you're not running on Lambda. You can set them up via long-lived AWS access keys or IAM roles with SSO. |
| 183 | + |
| 184 | +## Permissions per function |
| 185 | + |
| 186 | +If you want to define permissions **per function**, instead of globally (ie: in the provider), you can install the plugin [`serverless-iam-roles-per-function`](https://github.com/functionalone/serverless-iam-roles-per-function) and then use the `iamRoleStatements` at the function definition block. |
| 187 | + |
| 188 | +## Learn more |
| 189 | + |
| 190 | +- [`serverless.yml` IAM guide](https://github.com/oss-serverless/serverless/blob/main/docs/guides/iam.md) |
| 191 | +- [Documentation of the AWS SDK for PHP](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/) |
0 commit comments