Coverage for gco/stacks/aws_load_balancer_controller_policy.py: 83.33%

10 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-30 21:22 +0000

1"""Pinned AWS Load Balancer Controller v3.4.2 IAM policy. 

2 

3The JSON body is the exact upstream ``docs/install/iam_policy.json`` from tag 

4``v3.4.2``. Only the ARN partition is substituted at synth time so the same 

5policy works in every AWS partition supported by GCO. 

6 

7Source: 

8https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v3.4.2/docs/install/iam_policy.json 

9""" 

10 

11from __future__ import annotations 

12 

13import json 

14from typing import Any 

15 

16_AWS_LOAD_BALANCER_CONTROLLER_POLICY_V3_4_2 = r""" 

17{ 

18 "Version": "2012-10-17", 

19 "Statement": [ 

20 { 

21 "Effect": "Allow", 

22 "Action": [ 

23 "iam:CreateServiceLinkedRole" 

24 ], 

25 "Resource": "*", 

26 "Condition": { 

27 "StringEquals": { 

28 "iam:AWSServiceName": "elasticloadbalancing.amazonaws.com" 

29 } 

30 } 

31 }, 

32 { 

33 "Effect": "Allow", 

34 "Action": [ 

35 "ec2:DescribeAccountAttributes", 

36 "ec2:DescribeAddresses", 

37 "ec2:DescribeAvailabilityZones", 

38 "ec2:DescribeInternetGateways", 

39 "ec2:DescribeVpcs", 

40 "ec2:DescribeVpcPeeringConnections", 

41 "ec2:DescribeSubnets", 

42 "ec2:DescribeSecurityGroups", 

43 "ec2:DescribeInstances", 

44 "ec2:DescribeNetworkInterfaces", 

45 "ec2:DescribeTags", 

46 "ec2:GetCoipPoolUsage", 

47 "ec2:DescribeCoipPools", 

48 "ec2:GetSecurityGroupsForVpc", 

49 "ec2:DescribeIpamPools", 

50 "ec2:DescribeRouteTables", 

51 "elasticloadbalancing:DescribeLoadBalancers", 

52 "elasticloadbalancing:DescribeLoadBalancerAttributes", 

53 "elasticloadbalancing:DescribeListeners", 

54 "elasticloadbalancing:DescribeListenerCertificates", 

55 "elasticloadbalancing:DescribeSSLPolicies", 

56 "elasticloadbalancing:DescribeRules", 

57 "elasticloadbalancing:DescribeTargetGroups", 

58 "elasticloadbalancing:DescribeTargetGroupAttributes", 

59 "elasticloadbalancing:DescribeTargetHealth", 

60 "elasticloadbalancing:DescribeTags", 

61 "elasticloadbalancing:DescribeTrustStores", 

62 "elasticloadbalancing:DescribeListenerAttributes", 

63 "elasticloadbalancing:DescribeCapacityReservation" 

64 ], 

65 "Resource": "*" 

66 }, 

67 { 

68 "Effect": "Allow", 

69 "Action": [ 

70 "cognito-idp:DescribeUserPoolClient", 

71 "acm:ListCertificates", 

72 "acm:DescribeCertificate", 

73 "iam:ListServerCertificates", 

74 "iam:GetServerCertificate", 

75 "waf-regional:GetWebACL", 

76 "waf-regional:GetWebACLForResource", 

77 "waf-regional:AssociateWebACL", 

78 "waf-regional:DisassociateWebACL", 

79 "wafv2:GetWebACL", 

80 "wafv2:GetWebACLForResource", 

81 "wafv2:AssociateWebACL", 

82 "wafv2:DisassociateWebACL", 

83 "shield:GetSubscriptionState", 

84 "shield:DescribeProtection", 

85 "shield:CreateProtection", 

86 "shield:DeleteProtection" 

87 ], 

88 "Resource": "*" 

89 }, 

90 { 

91 "Effect": "Allow", 

92 "Action": [ 

93 "ec2:AuthorizeSecurityGroupIngress", 

94 "ec2:RevokeSecurityGroupIngress" 

95 ], 

96 "Resource": "*" 

97 }, 

98 { 

99 "Effect": "Allow", 

100 "Action": [ 

101 "ec2:CreateSecurityGroup" 

102 ], 

103 "Resource": "*" 

104 }, 

105 { 

106 "Effect": "Allow", 

107 "Action": [ 

108 "ec2:CreateTags" 

109 ], 

110 "Resource": "arn:aws:ec2:*:*:security-group/*", 

111 "Condition": { 

112 "StringEquals": { 

113 "ec2:CreateAction": "CreateSecurityGroup" 

114 }, 

115 "Null": { 

116 "aws:RequestTag/elbv2.k8s.aws/cluster": "false" 

117 } 

118 } 

119 }, 

120 { 

121 "Effect": "Allow", 

122 "Action": [ 

123 "ec2:CreateTags", 

124 "ec2:DeleteTags" 

125 ], 

126 "Resource": "arn:aws:ec2:*:*:security-group/*", 

127 "Condition": { 

128 "Null": { 

129 "aws:RequestTag/elbv2.k8s.aws/cluster": "true", 

130 "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" 

131 } 

132 } 

133 }, 

134 { 

135 "Effect": "Allow", 

136 "Action": [ 

137 "ec2:AuthorizeSecurityGroupIngress", 

138 "ec2:RevokeSecurityGroupIngress", 

139 "ec2:DeleteSecurityGroup" 

140 ], 

141 "Resource": "*", 

142 "Condition": { 

143 "Null": { 

144 "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" 

145 } 

146 } 

147 }, 

148 { 

149 "Effect": "Allow", 

150 "Action": [ 

151 "elasticloadbalancing:CreateLoadBalancer", 

152 "elasticloadbalancing:CreateTargetGroup" 

153 ], 

154 "Resource": "*", 

155 "Condition": { 

156 "Null": { 

157 "aws:RequestTag/elbv2.k8s.aws/cluster": "false" 

158 } 

159 } 

160 }, 

161 { 

162 "Effect": "Allow", 

163 "Action": [ 

164 "elasticloadbalancing:CreateListener", 

165 "elasticloadbalancing:DeleteListener", 

166 "elasticloadbalancing:CreateRule", 

167 "elasticloadbalancing:DeleteRule" 

168 ], 

169 "Resource": "*" 

170 }, 

171 { 

172 "Effect": "Allow", 

173 "Action": [ 

174 "elasticloadbalancing:AddTags", 

175 "elasticloadbalancing:RemoveTags" 

176 ], 

177 "Resource": [ 

178 "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*", 

179 "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*", 

180 "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" 

181 ], 

182 "Condition": { 

183 "Null": { 

184 "aws:RequestTag/elbv2.k8s.aws/cluster": "true", 

185 "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" 

186 } 

187 } 

188 }, 

189 { 

190 "Effect": "Allow", 

191 "Action": [ 

192 "elasticloadbalancing:AddTags", 

193 "elasticloadbalancing:RemoveTags" 

194 ], 

195 "Resource": [ 

196 "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*", 

197 "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*", 

198 "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*", 

199 "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*" 

200 ] 

201 }, 

202 { 

203 "Effect": "Allow", 

204 "Action": [ 

205 "elasticloadbalancing:ModifyLoadBalancerAttributes", 

206 "elasticloadbalancing:SetIpAddressType", 

207 "elasticloadbalancing:SetSecurityGroups", 

208 "elasticloadbalancing:SetSubnets", 

209 "elasticloadbalancing:DeleteLoadBalancer", 

210 "elasticloadbalancing:ModifyTargetGroup", 

211 "elasticloadbalancing:ModifyTargetGroupAttributes", 

212 "elasticloadbalancing:DeleteTargetGroup", 

213 "elasticloadbalancing:ModifyListenerAttributes", 

214 "elasticloadbalancing:ModifyCapacityReservation", 

215 "elasticloadbalancing:ModifyIpPools" 

216 ], 

217 "Resource": "*", 

218 "Condition": { 

219 "Null": { 

220 "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" 

221 } 

222 } 

223 }, 

224 { 

225 "Effect": "Allow", 

226 "Action": [ 

227 "elasticloadbalancing:AddTags" 

228 ], 

229 "Resource": [ 

230 "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*", 

231 "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*", 

232 "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" 

233 ], 

234 "Condition": { 

235 "StringEquals": { 

236 "elasticloadbalancing:CreateAction": [ 

237 "CreateTargetGroup", 

238 "CreateLoadBalancer" 

239 ] 

240 }, 

241 "Null": { 

242 "aws:RequestTag/elbv2.k8s.aws/cluster": "false" 

243 } 

244 } 

245 }, 

246 { 

247 "Effect": "Allow", 

248 "Action": [ 

249 "elasticloadbalancing:RegisterTargets", 

250 "elasticloadbalancing:DeregisterTargets" 

251 ], 

252 "Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" 

253 }, 

254 { 

255 "Effect": "Allow", 

256 "Action": [ 

257 "elasticloadbalancing:SetWebAcl", 

258 "elasticloadbalancing:ModifyListener", 

259 "elasticloadbalancing:AddListenerCertificates", 

260 "elasticloadbalancing:RemoveListenerCertificates", 

261 "elasticloadbalancing:ModifyRule", 

262 "elasticloadbalancing:SetRulePriorities" 

263 ], 

264 "Resource": "*" 

265 } 

266 ] 

267} 

268""" 

269 

270 

271def aws_load_balancer_controller_policy_document(partition: str) -> dict[str, Any]: 

272 """Return a fresh policy document with only ARN partitions substituted.""" 

273 if not partition or ":" in partition: 273 ↛ 274line 273 didn't jump to line 274 because the condition on line 273 was never true

274 raise ValueError(f"Invalid AWS partition: {partition!r}") 

275 document = _AWS_LOAD_BALANCER_CONTROLLER_POLICY_V3_4_2.replace("arn:aws:", f"arn:{partition}:") 

276 parsed = json.loads(document) 

277 if not isinstance(parsed, dict): # pragma: no cover - pinned literal invariant 

278 raise RuntimeError("Pinned AWS Load Balancer Controller policy is not an object") 

279 return parsed