(ecs): ContainerImage.from_asset incorrectly states the default follow_symlinks mode is NEVER
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
The [documentation of ContainerImage](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_ecs/ContainerImage.html) states:
> follow_symlinks (Optional[[SymlinkFollowMode](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/SymlinkFollowMode.html#aws_cdk.SymlinkFollowMode)]) – A strategy for how to handle symlinks. Default: SymlinkFollowMode.NEVER
As best as I can tell, this documentation comes from [CopyOptions or FileCopyOptions](https://github.com/aws/aws-cdk/blob/v2.33.0/packages/@aws-cdk/core/lib/fs/options.ts#L77-L99). However I do not see this behavior during actual usage.
If I use ContainerImage.from_asset and use Dockerfile that copies a symlink that references a file outside of the directory the Dockerfile is in, I'd expect that build to fail when using SymlinkFollowMode.NEVER. However the build succeeds, and in the Docker image is built, I see no symlink, only the file that is symlinked to.
When I explicitly set `follow_symlinks` to `SymlinkFollowMode.NEVER`, I see the expected failure.
It's again hard to work out just how the `follow_symlinks` value actually affects the build logic, but I think the offending code is in the core function [copyDirectory](https://github.com/aws/aws-cdk/blob/v2.33.0/packages/@aws-cdk/core/lib/fs/copy.ts#L8), which begins:
```
export function copyDirectory(srcDir: string, destDir: string, options: CopyOptions = { }, rootDir?: string) {
const follow = options.follow ?? SymlinkFollowMode.EXTERNAL;
```
Defaulting the SymlinkFollowMode to EXTERNAL. This matches the behavior I'm seeing.
### Expected Behavior
The ContainerImage.from_asset parameter follow_symlinks defaults to SymlinkFollowMode.NEVER, as per the documentation
### Current Behavior
The ContainerImage.from_asset parameter follow_symlinks appears to default to SymlinkFollowMode.EXTERNAL
### Reproduction Steps
The stack definition
```
from aws_cdk import Stack, aws_ecs, SymlinkFollowMode
from constructs import Construct
class DockerImageDemoStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
fargate_task_definition = aws_ecs.FargateTaskDefinition(
scope=self,
id="FargateTaskDefinition",
cpu=1024,
memory_limit_mib=2048,
)
fargate_task_definition.add_container(
id="Container",
image=aws_ecs.ContainerImage.from_asset(
"docker_images/test",
# follow_symlinks=SymlinkFollowMode.NEVER,
),
)
```
With docker_images/test containing the Dockerfile
```
FROM debian:bullseye-slim
# This line should not work in our build, as app.py is outside the docker_images/test context
# directory. It does fail from a direct docker build, but the CDK will allow the COPY.
COPY app.py .
```
And an app.py symlink created by executing:
```
cd docker_images/test && ln -s ../../app.py app.py && cd -
```
### Possible Solution
I suspect for backwards compatibility reasons this should be a documentation fix. However it seems like NEVER really should be the default, both so that the default behavior matches what you'd see with a `docker build`, and because of the security implications that copy operations can materialize files from the user’s file system.
### Additional Information/Context
It would be nice if the documentation included a recipe for duplicating what SymlinkFollowMode.EXTERNAL actually does to materialize the symlinks. For most of our docker images we've been able to cd into the directory the Dockerfile is contained in, and `docker build` and `docker run` to test the images locally.
However one of my colleagues has used some symlinks with one of his docker files, and now I'm not sure what the best way to build it locally is.
### CDK CLI Version
2.33.0 (build 859272d)
### Framework Version
_No response_
### Node.js Version
v16.15.1
### OS
Ubuntu (Windows Subsystem for Linux)
### Language
Python
### Language Version
Python 3.9.7
### Other information
_No response_
Contributor guide
Research direction
Start with ContainerImage.from_asset and inspect packages/@aws-cdk/core/lib/fs/options.ts and packages/@aws-cdk/core/lib/fs/copy.ts, especially the documented and effective defaults. Reproduce the behavior using the Dockerfile and external app.py symlink described in the issue. Done means the implementation and documentation agree on the default, with coverage for the reported case and explicit SymlinkFollowMode.NEVER behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, docker, python, typescript
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100