-
-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix bug atmos vendor pull URI cannot contain path traversal sequences and git schema #899
base: main
Are you sure you want to change the base?
Changes from 8 commits
063f955
201b521
88d043e
46edee4
8c6d2e0
bced3b5
d0490de
4b3c662
2f3690f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
base_path: "./" | ||
|
||
components: | ||
terraform: | ||
base_path: "components/terraform" | ||
apply_auto_approve: false | ||
deploy_run_init: true | ||
init_run_reconfigure: true | ||
auto_generate_backend_file: false | ||
|
||
stacks: | ||
base_path: "stacks" | ||
included_paths: | ||
- "deploy/**/*" | ||
excluded_paths: | ||
- "**/_defaults.yaml" | ||
name_pattern: "{stage}" | ||
|
||
vendor: | ||
# Single file | ||
base_path: "./vendor.yaml" | ||
|
||
# Directory with multiple files | ||
#base_path: "./vendor" | ||
|
||
# Absolute path | ||
#base_path: "vendor.d/vendor1.yaml" | ||
|
||
logs: | ||
file: "/dev/stderr" | ||
level: Info | ||
|
||
# Custom CLI commands | ||
|
||
# No arguments or flags are required | ||
commands: | ||
- name: "test" | ||
description: "Run all tests" | ||
steps: | ||
- atmos vendor pull --everything | ||
Comment on lines
+36
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Consider using explicit component selection instead of --everything flag The
Instead of using
This provides better control over which components are pulled during testing and makes the dependencies more explicit. 🔗 Analysis chainReview security implications of the --everything flag. The 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check what components would be pulled with --everything flag
atmos vendor pull --dry-run --everything
Length of output: 138 Script: #!/bin/bash
# Let's check the vendor configuration and related files
fd vendor -t f
# Check for any documentation or configuration related to vendor components
rg -i "vendor" -g "*.{md,yaml,yml}" -A 3 -B 3
Length of output: 34075 Script: #!/bin/bash
# Let's check the vendor.yaml file in the test-vendor directory to understand the configuration
cat examples/tests/test-vendor/vendor.yaml
# Let's also check if there are any specific components or tags defined
rg "component:|tags:" examples/tests/test-vendor/vendor.yaml -A 2
Length of output: 2092 🧰 Tools🪛 yamllint (1.35.1)[warning] 37-37: wrong indentation: expected 2 but found 0 (indentation) [warning] 40-40: wrong indentation: expected 4 but found 2 (indentation) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Example Terraform IPinfo Component | ||
|
||
This Terraform module retrieves data from the IPinfo API for a specified IP address. If no IP address is specified, it retrieves data for the requester's IP address. | ||
|
||
## Usage | ||
|
||
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add usage examples and prerequisites. The Usage section would benefit from:
Here's a suggested structure: ## Usage
### Prerequisites
- Terraform >= 0.13
- IPinfo API token (if required)
### Provider Configuration
```hcl
provider "http" {} Example Usagemodule "ipinfo" {
source = "path/to/module"
ip_address = "8.8.8.8" # Optional: Specify an IP address
}
output "ip_metadata" {
value = module.ipinfo.metadata
}
|
||
### Inputs | ||
|
||
- `ip_address` (optional): The IP address to retrieve information for. If not specified, the requester's IP address will be used. The default value is an empty string. | ||
|
||
### Outputs | ||
|
||
- `metadata`: The data retrieved from IPinfo for the specified IP address, in JSON format. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
data "http" "ipinfo" { | ||
url = var.ip_address != "" ? "https://ipinfo.io/${var.ip_address}" : "https://ipinfo.io" | ||
|
||
request_headers = { | ||
Accept = "application/json" | ||
} | ||
} | ||
osterman marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
output "metadata" { | ||
description = "The data retrieved from IPinfo for the specified IP address" | ||
value = jsondecode(data.http.ipinfo.response_body) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
provider "http" {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
variable "ip_address" { | ||
description = "The IP address to retrieve information for (optional)" | ||
type = string | ||
default = "" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
terraform { | ||
required_version = ">= 1.0.0" | ||
|
||
required_providers {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
apiVersion: atmos/v1 | ||
kind: AtmosVendorConfig | ||
metadata: | ||
name: demo-vendoring | ||
description: Atmos vendoring manifest for Atmos demo component library | ||
spec: | ||
# Import other vendor manifests, if necessary | ||
imports: [] | ||
|
||
sources: | ||
- component: "github/stargazers" | ||
source: "github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" | ||
version: "main" | ||
targets: | ||
- "components/terraform/{{ .Component }}/{{.Version}}" | ||
included_paths: | ||
- "**/*.tf" | ||
- "**/*.tfvars" | ||
- "**/*.md" | ||
tags: | ||
- demo | ||
- github | ||
|
||
- component: "test-components" | ||
source: "file:///./test-components" | ||
version: "main" | ||
targets: | ||
- "components/terraform/{{ .Component }}/{{.Version}}" | ||
tags: | ||
- demo | ||
|
||
- component: "weather" | ||
source: "git::https://github.com/cloudposse/atmos.git//examples/demo-library/{{ .Component }}?ref={{.Version}}" | ||
version: "main" | ||
targets: | ||
- "components/terraform/{{ .Component }}/{{.Version}}" | ||
tags: | ||
- demo | ||
- component: "my-vpc1" | ||
source: "oci://public.ecr.aws/cloudposse/components/terraform/stable/aws/vpc:{{.Version}}" | ||
version: "latest" | ||
targets: | ||
- "components/terraform/infra/my-vpc1" | ||
osterman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- component: "vpc-src" | ||
source: "../../demo-library/weather" # required for test URI contain path traversal | ||
targets: | ||
- "components/terraform/vpc-src" | ||
included_paths: | ||
- "**/*.tf" | ||
- "**/*.md" | ||
- "**/*.tftmpl" | ||
- "**/modules/**" | ||
excluded_paths: [] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package exec | |
|
||
import ( | ||
"fmt" | ||
"net/url" | ||
"os" | ||
"path/filepath" | ||
"sort" | ||
|
@@ -361,12 +362,14 @@ func ExecuteAtmosVendorInternal( | |
if err != nil { | ||
return err | ||
} | ||
err = ValidateURI(uri) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
useOciScheme, useLocalFileSystem, sourceIsLocalFile := determineSourceType(&uri, vendorConfigFilePath) | ||
if !useLocalFileSystem { | ||
err = ValidateURI(uri) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// Determine package type | ||
var pType pkgType | ||
|
@@ -384,7 +387,7 @@ func ExecuteAtmosVendorInternal( | |
if err != nil { | ||
return err | ||
} | ||
targetPath := filepath.Join(vendorConfigFilePath, target) | ||
targetPath := filepath.Join(filepath.ToSlash(vendorConfigFilePath), filepath.ToSlash(target)) | ||
pkgName := s.Component | ||
if pkgName == "" { | ||
pkgName = uri | ||
|
@@ -514,12 +517,22 @@ func determineSourceType(uri *string, vendorConfigFilePath string) (bool, bool, | |
useLocalFileSystem := false | ||
sourceIsLocalFile := false | ||
if !useOciScheme { | ||
if absPath, err := u.JoinAbsolutePathWithPath(vendorConfigFilePath, *uri); err == nil { | ||
if absPath, err := u.JoinAbsolutePathWithPath(filepath.ToSlash(vendorConfigFilePath), *uri); err == nil { | ||
uri = &absPath | ||
useLocalFileSystem = true | ||
sourceIsLocalFile = u.FileExists(*uri) | ||
} | ||
parsedURL, err := url.Parse(*uri) | ||
if err == nil && parsedURL.Scheme != "" { | ||
if parsedURL.Scheme == "file" { | ||
trimmedPath := strings.TrimPrefix(filepath.ToSlash(parsedURL.Path), "/") | ||
*uri = filepath.Clean(trimmedPath) | ||
useLocalFileSystem = true | ||
} | ||
} | ||
|
||
Comment on lines
+523
to
+536
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider handling URL parsing errors. While the URL parsing and file schema handling is good, the error from parsedURL, err := url.Parse(*uri)
- if err == nil && parsedURL.Scheme != "" {
+ if err != nil {
+ return useOciScheme, useLocalFileSystem, sourceIsLocalFile
+ }
+ if parsedURL.Scheme != "" {
if parsedURL.Scheme == "file" {
trimmedPath := strings.TrimPrefix(filepath.ToSlash(parsedURL.Path), "/")
*uri = filepath.Clean(trimmedPath)
|
||
} | ||
|
||
return useOciScheme, useLocalFileSystem, sourceIsLocalFile | ||
} | ||
|
||
|
@@ -556,6 +569,8 @@ func generateSkipFunction(atmosConfig schema.AtmosConfiguration, tempDir string, | |
if filepath.Base(src) == ".git" { | ||
return true, nil | ||
} | ||
tempDir = filepath.ToSlash(tempDir) | ||
src = filepath.ToSlash(src) | ||
|
||
trimmedSrc := u.TrimBasePathFromPath(tempDir+"/", src) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,3 +130,67 @@ tests: | |
stderr: | ||
- "^$" | ||
exit_code: 0 | ||
|
||
- name: atmos greet with args | ||
enabled: true | ||
description: "Validate atmos custom command greet runs with argument provided." | ||
workdir: "../examples/demo-custom-command/" | ||
command: "atmos" | ||
args: | ||
- "greet" | ||
- "Andrey" | ||
expect: | ||
stdout: | ||
- "Hello, Andrey\n" | ||
stderr: | ||
- "^$" | ||
exit_code: 0 | ||
|
||
- name: atmos greet without args | ||
enabled: true | ||
description: "Validate atmos custom command greet runs without argument provided." | ||
workdir: "../examples/demo-custom-command/" | ||
command: "atmos" | ||
args: | ||
- "greet" | ||
expect: | ||
stdout: | ||
- "Hello, John Doe\n" | ||
stderr: | ||
- "^$" | ||
exit_code: 0 | ||
- name: atmos_vendor_pull | ||
enabled: true | ||
description: "Ensure atmos vendor pull command executes without errors and files are present." | ||
workdir: "../examples/tests/test-vendor/" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use test fixtures instead |
||
command: "atmos" | ||
args: | ||
- "vendor" | ||
- "pull" | ||
expect: | ||
file_exists: | ||
- "./components/terraform/github/stargazers/main/main.tf" | ||
- "./components/terraform/github/stargazers/main/outputs.tf" | ||
- "./components/terraform/github/stargazers/main/providers.tf" | ||
- "./components/terraform/github/stargazers/main/variables.tf" | ||
- "./components/terraform/github/stargazers/main/versions.tf" | ||
- "./components/terraform/infra/my-vpc1/main.tf" | ||
- "./components/terraform/infra/my-vpc1/outputs.tf" | ||
- "./components/terraform/infra/my-vpc1/providers.tf" | ||
- "./components/terraform/infra/my-vpc1/variables.tf" | ||
- "./components/terraform/infra/my-vpc1/versions.tf" | ||
- "./components/terraform/test-components/main/main.tf" | ||
- "./components/terraform/test-components/main/outputs.tf" | ||
- "./components/terraform/test-components/main/providers.tf" | ||
- "./components/terraform/test-components/main/variables.tf" | ||
- "./components/terraform/test-components/main/versions.tf" | ||
- "./components/terraform/weather/main/main.tf" | ||
- "./components/terraform/weather/main/outputs.tf" | ||
- "./components/terraform/weather/main/providers.tf" | ||
- "./components/terraform/weather/main/variables.tf" | ||
- "./components/terraform/weather/main/versions.tf" | ||
- "./components/terraform/vpc-src/main.tf" | ||
- "./components/terraform/vpc-src/outputs.tf" | ||
- "./components/terraform/vpc-src/variables.tf" | ||
- "./components/terraform/vpc-src/versions.tf" | ||
exit_code: 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This directory has moved to tests/fixtures/scenarios