@intentius/chant-lexicon-azure 0.124.30 → 0.124.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/appservice.js +7 -0
- package/dist/actions/compute.js +9 -0
- package/dist/actions/container.js +14 -0
- package/dist/actions/identity.js +11 -0
- package/dist/actions/index.js +11 -0
- package/dist/actions/keyvault.js +12 -0
- package/dist/actions/network.js +9 -0
- package/dist/actions/sql.js +9 -0
- package/dist/actions/storage.js +15 -0
- package/dist/api/read-client.js +146 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +83 -0
- package/dist/codegen/generate-cli.js +11 -0
- package/dist/codegen/generate-lexicon.js +77 -0
- package/dist/codegen/generate-typescript.js +163 -0
- package/dist/codegen/generate.js +106 -0
- package/dist/codegen/naming.js +139 -0
- package/dist/codegen/package.js +64 -0
- package/dist/composites/aks-cluster.js +68 -0
- package/dist/composites/app-service.js +62 -0
- package/dist/composites/application-gateway.js +107 -0
- package/dist/composites/catalog.js +856 -0
- package/dist/composites/container-instance.js +36 -0
- package/dist/composites/container-registry.js +62 -0
- package/dist/composites/cosmos-database.js +56 -0
- package/dist/composites/from-arm.js +47 -0
- package/dist/composites/function-app.js +57 -0
- package/dist/composites/index.js +16 -0
- package/dist/composites/keyvault.js +69 -0
- package/dist/composites/landing-zone.js +119 -0
- package/dist/composites/private-endpoint.js +61 -0
- package/dist/composites/redis-cache.js +21 -0
- package/dist/composites/service-bus-pipeline.js +54 -0
- package/dist/composites/sql-database.js +62 -0
- package/dist/composites/storage-account.js +59 -0
- package/dist/composites/vm-linux.js +139 -0
- package/dist/composites/vnet-default.js +102 -0
- package/dist/coverage.js +28 -0
- package/dist/deep-observe.js +356 -0
- package/dist/default-tags.js +50 -0
- package/dist/deploy-scopes.d.ts.map +1 -1
- package/dist/deploy-scopes.js +157 -0
- package/dist/describe-resources.js +187 -0
- package/dist/detect.js +17 -0
- package/dist/export-resources.js +108 -0
- package/dist/generated/index.js +16598 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/governance.js +144 -0
- package/dist/import/generator.js +140 -0
- package/dist/import/live-export.js +39 -0
- package/dist/import/parser.js +192 -0
- package/dist/index.js +44 -0
- package/dist/integrity.json +2 -2
- package/dist/intrinsics.js +179 -0
- package/dist/lint/audit-catalog.js +36 -0
- package/dist/lint/audit-lineage.js +71 -0
- package/dist/lint/post-synth/arm-refs.js +94 -0
- package/dist/lint/post-synth/azr010.js +45 -0
- package/dist/lint/post-synth/azr011.js +43 -0
- package/dist/lint/post-synth/azr012.js +41 -0
- package/dist/lint/post-synth/azr013.js +50 -0
- package/dist/lint/post-synth/azr014.js +49 -0
- package/dist/lint/post-synth/azr015.js +66 -0
- package/dist/lint/post-synth/azr016.js +37 -0
- package/dist/lint/post-synth/azr017.js +37 -0
- package/dist/lint/post-synth/azr018.js +42 -0
- package/dist/lint/post-synth/azr019.js +41 -0
- package/dist/lint/post-synth/azr020.js +37 -0
- package/dist/lint/post-synth/azr021.js +36 -0
- package/dist/lint/post-synth/azr022.js +39 -0
- package/dist/lint/post-synth/azr023.js +39 -0
- package/dist/lint/post-synth/azr024.js +39 -0
- package/dist/lint/post-synth/azr025.js +37 -0
- package/dist/lint/post-synth/azr026.js +38 -0
- package/dist/lint/post-synth/azr027.js +37 -0
- package/dist/lint/post-synth/azr028.js +37 -0
- package/dist/lint/post-synth/azr029.js +38 -0
- package/dist/lint/post-synth/azr030.js +44 -0
- package/dist/lint/post-synth/azr031.js +36 -0
- package/dist/lint/post-synth/azr032.js +53 -0
- package/dist/lint/post-synth/azr033.js +35 -0
- package/dist/lint/post-synth/index.js +50 -0
- package/dist/lint/rules/hardcoded-location.js +82 -0
- package/dist/lint/rules/index.js +6 -0
- package/dist/lint/rules/nsg-wildcard.js +44 -0
- package/dist/lint/rules/storage-https.js +62 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +44 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/az-apply.js +563 -0
- package/dist/op/activities/azure.js +48 -0
- package/dist/op/activities/floci-az.js +37 -0
- package/dist/op/activities/index.js +10 -0
- package/dist/op/builders.js +70 -0
- package/dist/ownership.js +13 -0
- package/dist/package-cli.js +21 -0
- package/dist/parameter.js +13 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +472 -0
- package/dist/pseudo.js +40 -0
- package/dist/serializer.js +457 -0
- package/dist/spec/api-versions.js +130 -0
- package/dist/spec/fetch.js +196 -0
- package/dist/spec/parse.js +308 -0
- package/dist/taggable.js +34 -0
- package/dist/validate-cli.js +16 -0
- package/dist/validate.js +53 -0
- package/package.json +8 -8
- package/src/codegen/package.ts +2 -2
- package/src/deploy-scopes.ts +2 -1
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/plugin.ts +3 -2
- package/src/serializer.ts +2 -2
- package/src/taggable.ts +2 -2
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AZR031: Policy Assignment Not Enforced
|
|
3
|
+
*
|
|
4
|
+
* Flags Microsoft.Authorization/policyAssignments with enforcementMode
|
|
5
|
+
* DoNotEnforce. The assignment stays visible in the tree while denying
|
|
6
|
+
* nothing — the Azure shape of a disabled guardrail.
|
|
7
|
+
*/
|
|
8
|
+
import { parseArmTemplate } from "./arm-refs.js";
|
|
9
|
+
export const azr031 = {
|
|
10
|
+
id: "AZR031",
|
|
11
|
+
description: "Policy assignment has enforcementMode DoNotEnforce — the guardrail is disabled",
|
|
12
|
+
check(ctx) {
|
|
13
|
+
const diagnostics = [];
|
|
14
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
15
|
+
const template = parseArmTemplate(output);
|
|
16
|
+
if (!template?.resources)
|
|
17
|
+
continue;
|
|
18
|
+
for (const resource of template.resources) {
|
|
19
|
+
if (resource.type !== "Microsoft.Authorization/policyAssignments")
|
|
20
|
+
continue;
|
|
21
|
+
const mode = resource.properties?.enforcementMode;
|
|
22
|
+
if (mode !== "DoNotEnforce")
|
|
23
|
+
continue;
|
|
24
|
+
const name = typeof resource.name === "string" ? resource.name : String(resource.name);
|
|
25
|
+
diagnostics.push({
|
|
26
|
+
checkId: "AZR031",
|
|
27
|
+
severity: "error",
|
|
28
|
+
message: `Policy assignment "${name}" has enforcementMode DoNotEnforce — the guardrail is assigned but enforces nothing`,
|
|
29
|
+
entity: name,
|
|
30
|
+
lexicon: "azure",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return diagnostics;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AZR032: Policy Definition Assigned Nowhere
|
|
3
|
+
*
|
|
4
|
+
* Flags custom Microsoft.Authorization/policyDefinitions with no
|
|
5
|
+
* policyAssignments referencing them in the same template. The
|
|
6
|
+
* GovernanceBaseline composite always pairs definition and assignment; a
|
|
7
|
+
* definition alone is the leftover of a dropped guardrail assignment.
|
|
8
|
+
*/
|
|
9
|
+
import { parseArmTemplate } from "./arm-refs.js";
|
|
10
|
+
/**
|
|
11
|
+
* True when a policyDefinitionId expression targets the definition name —
|
|
12
|
+
* either a quoted literal inside resourceId()/managementGroupResourceId()
|
|
13
|
+
* or the trailing segment of a literal resource id.
|
|
14
|
+
*/
|
|
15
|
+
function references(definitionName, policyDefinitionId) {
|
|
16
|
+
if (typeof policyDefinitionId !== "string")
|
|
17
|
+
return false;
|
|
18
|
+
return (policyDefinitionId.includes(`'${definitionName}'`) ||
|
|
19
|
+
policyDefinitionId.endsWith(`/${definitionName}`) ||
|
|
20
|
+
policyDefinitionId === definitionName);
|
|
21
|
+
}
|
|
22
|
+
export const azr032 = {
|
|
23
|
+
id: "AZR032",
|
|
24
|
+
description: "Custom policy definition assigned nowhere — a defined but unassigned guardrail enforces nothing",
|
|
25
|
+
check(ctx) {
|
|
26
|
+
const diagnostics = [];
|
|
27
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
28
|
+
const template = parseArmTemplate(output);
|
|
29
|
+
if (!template?.resources)
|
|
30
|
+
continue;
|
|
31
|
+
const assignmentIds = template.resources
|
|
32
|
+
.filter((r) => r.type === "Microsoft.Authorization/policyAssignments")
|
|
33
|
+
.map((r) => r.properties?.policyDefinitionId);
|
|
34
|
+
for (const resource of template.resources) {
|
|
35
|
+
if (resource.type !== "Microsoft.Authorization/policyDefinitions")
|
|
36
|
+
continue;
|
|
37
|
+
if (typeof resource.name !== "string")
|
|
38
|
+
continue;
|
|
39
|
+
const name = resource.name;
|
|
40
|
+
if (assignmentIds.some((id) => references(name, id)))
|
|
41
|
+
continue;
|
|
42
|
+
diagnostics.push({
|
|
43
|
+
checkId: "AZR032",
|
|
44
|
+
severity: "error",
|
|
45
|
+
message: `Policy definition "${name}" is assigned nowhere in this template — pair it with a policy assignment or the guardrail enforces nothing`,
|
|
46
|
+
entity: name,
|
|
47
|
+
lexicon: "azure",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return diagnostics;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AZR033: Subscriptions May Leave the Tenant
|
|
3
|
+
*
|
|
4
|
+
* Flags a Microsoft.Subscription/policies resource that sets
|
|
5
|
+
* blockSubscriptionsLeavingTenant to false — the tenant-level leave-block
|
|
6
|
+
* the landing-zone foundation declares, explicitly weakened.
|
|
7
|
+
*/
|
|
8
|
+
import { parseArmTemplate } from "./arm-refs.js";
|
|
9
|
+
export const azr033 = {
|
|
10
|
+
id: "AZR033",
|
|
11
|
+
description: "Tenant subscription policy does not block subscriptions from leaving",
|
|
12
|
+
check(ctx) {
|
|
13
|
+
const diagnostics = [];
|
|
14
|
+
for (const [_lexicon, output] of ctx.outputs) {
|
|
15
|
+
const template = parseArmTemplate(output);
|
|
16
|
+
if (!template?.resources)
|
|
17
|
+
continue;
|
|
18
|
+
for (const resource of template.resources) {
|
|
19
|
+
if (resource.type !== "Microsoft.Subscription/policies")
|
|
20
|
+
continue;
|
|
21
|
+
if (resource.properties?.blockSubscriptionsLeavingTenant !== false)
|
|
22
|
+
continue;
|
|
23
|
+
const name = typeof resource.name === "string" ? resource.name : String(resource.name);
|
|
24
|
+
diagnostics.push({
|
|
25
|
+
checkId: "AZR033",
|
|
26
|
+
severity: "error",
|
|
27
|
+
message: `Subscription tenant policy "${name}" sets blockSubscriptionsLeavingTenant: false — subscriptions can be moved out of the tenant`,
|
|
28
|
+
entity: name,
|
|
29
|
+
lexicon: "azure",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return diagnostics;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { azr010 } from "./azr010.js";
|
|
2
|
+
import { azr011 } from "./azr011.js";
|
|
3
|
+
import { azr012 } from "./azr012.js";
|
|
4
|
+
import { azr013 } from "./azr013.js";
|
|
5
|
+
import { azr014 } from "./azr014.js";
|
|
6
|
+
import { azr015 } from "./azr015.js";
|
|
7
|
+
import { azr016 } from "./azr016.js";
|
|
8
|
+
import { azr017 } from "./azr017.js";
|
|
9
|
+
import { azr018 } from "./azr018.js";
|
|
10
|
+
import { azr019 } from "./azr019.js";
|
|
11
|
+
import { azr020 } from "./azr020.js";
|
|
12
|
+
import { azr021 } from "./azr021.js";
|
|
13
|
+
import { azr022 } from "./azr022.js";
|
|
14
|
+
import { azr023 } from "./azr023.js";
|
|
15
|
+
import { azr024 } from "./azr024.js";
|
|
16
|
+
import { azr025 } from "./azr025.js";
|
|
17
|
+
import { azr026 } from "./azr026.js";
|
|
18
|
+
import { azr027 } from "./azr027.js";
|
|
19
|
+
import { azr028 } from "./azr028.js";
|
|
20
|
+
import { azr029 } from "./azr029.js";
|
|
21
|
+
import { azr030 } from "./azr030.js";
|
|
22
|
+
import { azr031 } from "./azr031.js";
|
|
23
|
+
import { azr032 } from "./azr032.js";
|
|
24
|
+
import { azr033 } from "./azr033.js";
|
|
25
|
+
export const postSynthChecks = [
|
|
26
|
+
azr010,
|
|
27
|
+
azr011,
|
|
28
|
+
azr012,
|
|
29
|
+
azr013,
|
|
30
|
+
azr014,
|
|
31
|
+
azr015,
|
|
32
|
+
azr016,
|
|
33
|
+
azr017,
|
|
34
|
+
azr018,
|
|
35
|
+
azr019,
|
|
36
|
+
azr020,
|
|
37
|
+
azr021,
|
|
38
|
+
azr022,
|
|
39
|
+
azr023,
|
|
40
|
+
azr024,
|
|
41
|
+
azr025,
|
|
42
|
+
azr026,
|
|
43
|
+
azr027,
|
|
44
|
+
azr028,
|
|
45
|
+
azr029,
|
|
46
|
+
azr030,
|
|
47
|
+
azr031,
|
|
48
|
+
azr032,
|
|
49
|
+
azr033,
|
|
50
|
+
];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ts } from "@intentius/chant/lint/typescript";
|
|
2
|
+
/**
|
|
3
|
+
* AZR001: Hardcoded Azure Location
|
|
4
|
+
*
|
|
5
|
+
* Detects hardcoded Azure location strings in code.
|
|
6
|
+
* Locations should use Azure.ResourceGroupLocation pseudo-parameter instead.
|
|
7
|
+
*/
|
|
8
|
+
export const hardcodedLocationRule = {
|
|
9
|
+
id: "AZR001",
|
|
10
|
+
severity: "warning",
|
|
11
|
+
category: "correctness",
|
|
12
|
+
description: "Detects hardcoded Azure location strings — use Azure.ResourceGroupLocation instead",
|
|
13
|
+
check(context) {
|
|
14
|
+
const { sourceFile } = context;
|
|
15
|
+
const diagnostics = [];
|
|
16
|
+
// Common Azure location strings (case-insensitive match)
|
|
17
|
+
const azureLocations = new Set([
|
|
18
|
+
"eastus",
|
|
19
|
+
"eastus2",
|
|
20
|
+
"westus",
|
|
21
|
+
"westus2",
|
|
22
|
+
"westus3",
|
|
23
|
+
"centralus",
|
|
24
|
+
"northcentralus",
|
|
25
|
+
"southcentralus",
|
|
26
|
+
"westcentralus",
|
|
27
|
+
"canadacentral",
|
|
28
|
+
"canadaeast",
|
|
29
|
+
"brazilsouth",
|
|
30
|
+
"northeurope",
|
|
31
|
+
"westeurope",
|
|
32
|
+
"uksouth",
|
|
33
|
+
"ukwest",
|
|
34
|
+
"francecentral",
|
|
35
|
+
"francesouth",
|
|
36
|
+
"switzerlandnorth",
|
|
37
|
+
"switzerlandwest",
|
|
38
|
+
"germanywestcentral",
|
|
39
|
+
"norwayeast",
|
|
40
|
+
"norwaywest",
|
|
41
|
+
"swedencentral",
|
|
42
|
+
"eastasia",
|
|
43
|
+
"southeastasia",
|
|
44
|
+
"japaneast",
|
|
45
|
+
"japanwest",
|
|
46
|
+
"australiaeast",
|
|
47
|
+
"australiasoutheast",
|
|
48
|
+
"australiacentral",
|
|
49
|
+
"koreacentral",
|
|
50
|
+
"koreasouth",
|
|
51
|
+
"southafricanorth",
|
|
52
|
+
"southafricawest",
|
|
53
|
+
"uaenorth",
|
|
54
|
+
"uaecentral",
|
|
55
|
+
"centralindia",
|
|
56
|
+
"southindia",
|
|
57
|
+
"westindia",
|
|
58
|
+
"qatarcentral",
|
|
59
|
+
"polandcentral",
|
|
60
|
+
"italynorth",
|
|
61
|
+
]);
|
|
62
|
+
function visit(node) {
|
|
63
|
+
if (ts.isStringLiteral(node)) {
|
|
64
|
+
const value = node.text.toLowerCase();
|
|
65
|
+
if (azureLocations.has(value)) {
|
|
66
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
67
|
+
diagnostics.push({
|
|
68
|
+
file: sourceFile.fileName,
|
|
69
|
+
line: line + 1,
|
|
70
|
+
column: character + 1,
|
|
71
|
+
ruleId: "AZR001",
|
|
72
|
+
severity: "warning",
|
|
73
|
+
message: `Hardcoded location "${node.text}" detected. Use Azure.ResourceGroupLocation instead.`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
ts.forEachChild(node, visit);
|
|
78
|
+
}
|
|
79
|
+
visit(sourceFile);
|
|
80
|
+
return diagnostics;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ts } from "@intentius/chant/lint/typescript";
|
|
2
|
+
/**
|
|
3
|
+
* AZR003: NSG Wildcard Source Address
|
|
4
|
+
*
|
|
5
|
+
* Detects Network Security Group rules with sourceAddressPrefix: "*".
|
|
6
|
+
* Wildcard source addresses allow traffic from any source and should be
|
|
7
|
+
* restricted to specific IP ranges or service tags.
|
|
8
|
+
*/
|
|
9
|
+
export const nsgWildcardRule = {
|
|
10
|
+
id: "AZR003",
|
|
11
|
+
severity: "warning",
|
|
12
|
+
category: "security",
|
|
13
|
+
description: "Detects NSG rules with wildcard (*) source address — restrict to specific IP ranges or service tags",
|
|
14
|
+
check(context) {
|
|
15
|
+
const { sourceFile } = context;
|
|
16
|
+
const diagnostics = [];
|
|
17
|
+
function visit(node) {
|
|
18
|
+
// Look for sourceAddressPrefix: "*" in object literals
|
|
19
|
+
if (ts.isPropertyAssignment(node)) {
|
|
20
|
+
const name = node.name;
|
|
21
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
22
|
+
const propName = ts.isIdentifier(name) ? name.text : name.text;
|
|
23
|
+
if (propName === "sourceAddressPrefix") {
|
|
24
|
+
// Check if value is "*"
|
|
25
|
+
if (ts.isStringLiteral(node.initializer) && node.initializer.text === "*") {
|
|
26
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
27
|
+
diagnostics.push({
|
|
28
|
+
file: sourceFile.fileName,
|
|
29
|
+
line: line + 1,
|
|
30
|
+
column: character + 1,
|
|
31
|
+
ruleId: "AZR003",
|
|
32
|
+
severity: "warning",
|
|
33
|
+
message: "NSG rule uses wildcard (*) sourceAddressPrefix. Restrict to specific IP ranges or service tags.",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
ts.forEachChild(node, visit);
|
|
40
|
+
}
|
|
41
|
+
visit(sourceFile);
|
|
42
|
+
return diagnostics;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ts } from "@intentius/chant/lint/typescript";
|
|
2
|
+
/**
|
|
3
|
+
* AZR002: Storage Account HTTPS Only
|
|
4
|
+
*
|
|
5
|
+
* Detects Storage Account creation without supportsHttpsTrafficOnly: true.
|
|
6
|
+
* All storage accounts should enforce HTTPS-only traffic.
|
|
7
|
+
*/
|
|
8
|
+
export const storageHttpsRule = {
|
|
9
|
+
id: "AZR002",
|
|
10
|
+
severity: "warning",
|
|
11
|
+
category: "security",
|
|
12
|
+
description: "Detects Storage Accounts without supportsHttpsTrafficOnly enabled — all storage accounts should enforce HTTPS",
|
|
13
|
+
check(context) {
|
|
14
|
+
const { sourceFile } = context;
|
|
15
|
+
const diagnostics = [];
|
|
16
|
+
function visit(node) {
|
|
17
|
+
// Look for `new StorageAccount(...)` or `new storage.StorageAccount(...)`
|
|
18
|
+
if (ts.isNewExpression(node)) {
|
|
19
|
+
const expression = node.expression;
|
|
20
|
+
let isStorageAccount = false;
|
|
21
|
+
// Check for `new StorageAccount(...)`
|
|
22
|
+
if (ts.isIdentifier(expression) && expression.text === "StorageAccount") {
|
|
23
|
+
isStorageAccount = true;
|
|
24
|
+
}
|
|
25
|
+
// Check for `new storage.StorageAccount(...)` or `new azure.storage.StorageAccount(...)`
|
|
26
|
+
else if (ts.isPropertyAccessExpression(expression)) {
|
|
27
|
+
if (expression.name.text === "StorageAccount") {
|
|
28
|
+
isStorageAccount = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (isStorageAccount && node.arguments && node.arguments.length > 0) {
|
|
32
|
+
const props = node.arguments[0];
|
|
33
|
+
if (ts.isObjectLiteralExpression(props)) {
|
|
34
|
+
const hasHttpsOnly = props.properties.some((prop) => {
|
|
35
|
+
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
36
|
+
if (prop.name.text === "supportsHttpsTrafficOnly") {
|
|
37
|
+
// Check that it's set to true
|
|
38
|
+
return prop.initializer.kind === ts.SyntaxKind.TrueKeyword;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
});
|
|
43
|
+
if (!hasHttpsOnly) {
|
|
44
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
45
|
+
diagnostics.push({
|
|
46
|
+
file: sourceFile.fileName,
|
|
47
|
+
line: line + 1,
|
|
48
|
+
column: character + 1,
|
|
49
|
+
ruleId: "AZR002",
|
|
50
|
+
severity: "warning",
|
|
51
|
+
message: "Storage Account created without supportsHttpsTrafficOnly: true. Enable HTTPS-only traffic.",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
ts.forEachChild(node, visit);
|
|
58
|
+
}
|
|
59
|
+
visit(sourceFile);
|
|
60
|
+
return diagnostics;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/lsp/completions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/lsp/completions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAapF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,cAAc,EAAE,CAEzE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
import { moduleSourceUrl } from "@intentius/chant/module-source";
|
|
3
|
+
import { LexiconIndex, lexiconCompletions } from "@intentius/chant/lsp/lexicon-providers";
|
|
4
|
+
const require = createRequire(moduleSourceUrl(import.meta.url));
|
|
5
|
+
let cachedIndex = null;
|
|
6
|
+
function getIndex() {
|
|
7
|
+
if (cachedIndex)
|
|
8
|
+
return cachedIndex;
|
|
9
|
+
const data = require("../generated/lexicon-azure.json");
|
|
10
|
+
cachedIndex = new LexiconIndex(data);
|
|
11
|
+
return cachedIndex;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Provide Azure completions based on context.
|
|
15
|
+
*/
|
|
16
|
+
export function azureCompletions(ctx) {
|
|
17
|
+
return lexiconCompletions(ctx, getIndex(), "Azure ARM resource");
|
|
18
|
+
}
|
package/dist/lsp/hover.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/lsp/hover.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/lsp/hover.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAa1E;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,GAAG,SAAS,CAEnE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
import { moduleSourceUrl } from "@intentius/chant/module-source";
|
|
3
|
+
import { LexiconIndex, lexiconHover } from "@intentius/chant/lsp/lexicon-providers";
|
|
4
|
+
const require = createRequire(moduleSourceUrl(import.meta.url));
|
|
5
|
+
let cachedIndex = null;
|
|
6
|
+
function getIndex() {
|
|
7
|
+
if (cachedIndex)
|
|
8
|
+
return cachedIndex;
|
|
9
|
+
const data = require("../generated/lexicon-azure.json");
|
|
10
|
+
cachedIndex = new LexiconIndex(data);
|
|
11
|
+
return cachedIndex;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Provide hover information for Azure resource types and properties.
|
|
15
|
+
*/
|
|
16
|
+
export function azureHover(ctx) {
|
|
17
|
+
return lexiconHover(ctx, getIndex(), resourceHover);
|
|
18
|
+
}
|
|
19
|
+
function resourceHover(className, entry) {
|
|
20
|
+
if (entry.kind !== "resource")
|
|
21
|
+
return undefined;
|
|
22
|
+
const lines = [];
|
|
23
|
+
lines.push(`**${className}**`);
|
|
24
|
+
lines.push("");
|
|
25
|
+
lines.push(`ARM resource type: \`${entry.resourceType}\``);
|
|
26
|
+
const apiVersion = entry.apiVersion;
|
|
27
|
+
if (apiVersion) {
|
|
28
|
+
lines.push(`API version: \`${apiVersion}\``);
|
|
29
|
+
}
|
|
30
|
+
if (entry.attrs && Object.keys(entry.attrs).length > 0) {
|
|
31
|
+
lines.push("");
|
|
32
|
+
lines.push("**Attributes:**");
|
|
33
|
+
for (const [key, value] of Object.entries(entry.attrs)) {
|
|
34
|
+
lines.push(`- \`${key}\` → \`${value}\``);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const provider = entry.resourceType.split("/")[0]?.replace("Microsoft.", "").toLowerCase();
|
|
38
|
+
const resource = entry.resourceType.split("/").pop()?.toLowerCase();
|
|
39
|
+
if (provider && resource) {
|
|
40
|
+
lines.push("");
|
|
41
|
+
lines.push(`[Azure docs](https://learn.microsoft.com/en-us/azure/templates/${provider}/${resource})`);
|
|
42
|
+
}
|
|
43
|
+
return { contents: lines.join("\n") };
|
|
44
|
+
}
|