Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions iac/ql/lib/codeql/hcl/ast/AstNodes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ class HclAstNode extends THclAstNode {
* }
* ```
*/
class Comment extends HclAstNode, TComment {
class HCLComment extends HclAstNode, TComment {
private HCL::Comment comment;

override string getAPrimaryQlClass() { result = "Comment" }
override string getAPrimaryQlClass() { result = "HCLComment" }

Comment() { this = TComment(comment) }
HCLComment() { this = TComment(comment) }

/** Gets the textual contents of the comment. */
string getContents() { result = comment.getValue() }
Expand Down
93 changes: 93 additions & 0 deletions iac/ql/lib/codeql/iac/Comments.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* Provides a unified representation of comments across the infrastructure-as-code
* (IaC) languages supported by CodeQL, spanning HCL/Terraform comments and comments
* in YAML files recognized by a public IaC framework API.
*/

import iac

/**
* Holds if `file` is a YAML file recognized by a public IaC framework API.
*/
private predicate isSupportedYamlFile(File file) {
exists(CloudFormation::Document document | document.getFile() = file)
or
exists(ARM::Document document | document.getFile() = file)
or
exists(AzurePipelines::Document document | document.getFile() = file)
or
exists(Compose::Document document | document.getFile() = file)
or
exists(HelmChart::Document document | document.getFile() = file)
or
exists(OpenApi::Document document | document.getFile() = file)
or
exists(YamlDocument document |
document.getFile() = file and
document instanceof YamlMapping and
document
.(YamlMapping)
.lookup("$schema")
.(YamlString)
.getValue()
.regexpMatch(".*schema\\.management\\.azure\\.com.*")
)
}

/**
* Gets the delimiter-stripped `text` and `delimiterStyle` of an HCL comment.
*/
private predicate getHclCommentText(HCLComment comment, string text, string delimiterStyle) {
exists(string raw | raw = comment.getContents() |
raw.matches("#%") and
text = raw.suffix(1).replaceAll("\r", "") and
delimiterStyle = "hash"
or
raw.matches("//%") and
text = raw.suffix(2).replaceAll("\r", "") and
delimiterStyle = "slash"
or
raw.matches("/*%*/") and
text = raw.substring(2, raw.length() - 2).replaceAll("\r", "") and
delimiterStyle = "slash"
)
}

/**
* Gets the delimiter-stripped `text` and `delimiterStyle` of a comment exposed by a
* supported public IaC API located at `location`.
*/
private predicate getIacCommentText(Location location, string text, string delimiterStyle) {
exists(HCLComment comment |
location = comment.getLocation() and
getHclCommentText(comment, text, delimiterStyle)
)
or
exists(YamlComment comment |
location = comment.getLocation() and
isSupportedYamlFile(comment.getLocation().getFile()) and
text = comment.getText() and
delimiterStyle = "hash"
)
}

/**
* A comment exposed by a supported public IaC API.
*
* This spans HCL/Terraform comments and comments in YAML files recognized by a public
* IaC framework API (for example CloudFormation, ARM, Azure Pipelines, Compose, Helm
* charts and OpenAPI documents).
*/
class Comment extends Location {
Comment() {
exists(string text, string delimiterStyle | getIacCommentText(this, text, delimiterStyle))
}

/** Gets the comment text without its delimiter. */
string getText() {
exists(string delimiterStyle | getIacCommentText(this, result, delimiterStyle))
}

/** Holds if this comment uses `#` as its delimiter. */
predicate hasHashDelimiter() { exists(string text | getIacCommentText(this, text, "hash")) }
}
2 changes: 1 addition & 1 deletion iac/ql/lib/codeql/iac/ideContextual/printAstGenerated.qll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PrintAstConfiguration extends string {
* Holds if the given node should be printed.
*/
predicate shouldPrintNode(AstNode n) {
not n instanceof Comment and
not n instanceof HCLComment and
not n instanceof ReservedWord
}
}
Expand Down
1 change: 1 addition & 0 deletions iac/ql/lib/iac.qll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import codeql.Locations
import codeql.files.FileSystem
import codeql.iac.Comments
import codeql.iac.Dependencies
// Azure
import codeql.iac.azure.ARM
Expand Down
16 changes: 16 additions & 0 deletions iac/ql/test/library-tests/comments/Comments.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
iacComments
| sample.hcl:1:1:1:17 | sample.hcl@1:1:1:17 |
| sample.hcl:2:1:2:19 | sample.hcl@2:1:2:19 |
| sample.hcl:3:1:3:21 | sample.hcl@3:1:3:21 |
| sample.hcl:6:24:6:48 | sample.hcl@6:24:6:48 |
| template.yml:3:3:3:28 | template.yml@3:3:3:28 |
getText
| sample.hcl:1:1:1:17 | sample.hcl@1:1:1:17 | a hash comment |
| sample.hcl:2:1:2:19 | sample.hcl@2:1:2:19 | a slash comment |
| sample.hcl:3:1:3:21 | sample.hcl@3:1:3:21 | a block comment |
| sample.hcl:6:24:6:48 | sample.hcl@6:24:6:48 | an inline hash comment |
| template.yml:3:3:3:28 | template.yml@3:3:3:28 | a supported YAML comment |
hasHashDelimiter
| sample.hcl:1:1:1:17 | sample.hcl@1:1:1:17 |
| sample.hcl:6:24:6:48 | sample.hcl@6:24:6:48 |
| template.yml:3:3:3:28 | template.yml@3:3:3:28 |
7 changes: 7 additions & 0 deletions iac/ql/test/library-tests/comments/Comments.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
private import iac

query predicate iacComments(Comment c) { any() }

query predicate getText(Comment c, string text) { text = c.getText() }

query predicate hasHashDelimiter(Comment c) { c.hasHashDelimiter() }
7 changes: 7 additions & 0 deletions iac/ql/test/library-tests/comments/sample.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# a hash comment
// a slash comment
/* a block comment */

resource "aws_instance" "example" {
ami = "ami-12345678" # an inline hash comment
}
5 changes: 5 additions & 0 deletions iac/ql/test/library-tests/comments/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
AWSTemplateFormatVersion: "2010-09-09"
Resources:
# a supported YAML comment
ExampleBucket:
Type: AWS::S3::Bucket
2 changes: 2 additions & 0 deletions iac/ql/test/library-tests/comments/unsupported.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# an unsupported YAML comment that should be ignored
foo: bar
Loading