Skip to content

Commit f41e67e

Browse files
authored
Merge pull request #43 from provectus/jenkins-iam-role
Added IAM roles for Jenkins master and agents
2 parents 651b19f + d9ff2e5 commit f41e67e

File tree

9 files changed

+245
-5
lines changed

9 files changed

+245
-5
lines changed

example/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,7 @@ Refresh tfstate
6363

6464
Recreate resources
6565
`terraform taint module.system.null_resource.helm_init`
66+
67+
If `terraform destroy` command fails, run
68+
`destroy_fix.sh`
69+
and try `terraform destroy` again

example/destroy_fix.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
terraform show | grep -e "module.*helm" | tr -d '# :' | xargs terraform state rm
4+
terraform show | grep -e "module.*route53" | tr -d '# :' | xargs terraform state rm
5+
6+
terraform state rm module.nginx.kubernetes_namespace.ingress-system
7+
terraform state rm module.system.kubernetes_namespace.cert-manager

example/example.tfvars

+31
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,37 @@ elasticDataSize = "30Gi"
6464

6565
#Jenkins
6666
jenkins_password = "password"
67+
# Uncomment to attach S3 readonly policy for Jenkins master and agent IAM roles, or customize to add needed policies
68+
//agent_policy = <<EOF
69+
//{
70+
// "Version": "2012-10-17",
71+
// "Statement": [
72+
// {
73+
// "Effect": "Allow",
74+
// "Action": [
75+
// "s3:Get*",
76+
// "s3:List*"
77+
// ],
78+
// "Resource": "*"
79+
// }
80+
// ]
81+
//}
82+
//EOF
83+
//master_policy = <<EOF
84+
//{
85+
// "Version": "2012-10-17",
86+
// "Statement": [
87+
// {
88+
// "Effect": "Allow",
89+
// "Action": [
90+
// "s3:Get*",
91+
// "s3:List*"
92+
// ],
93+
// "Resource": "*"
94+
// }
95+
// ]
96+
//}
97+
//EOF
6798

6899
#Grafana
69100
grafana_password = "password"

example/modules.tf

+9
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,14 @@ module "jenkins" {
134134
domains = var.domains
135135
jenkins_password = var.jenkins_password
136136

137+
environment = var.environment
138+
project = var.project
139+
cluster_name = var.cluster_name
140+
cluster_oidc_url = module.kubernetes.cluster_oidc_url
141+
cluster_oidc_arn = module.system.oidc_arn
142+
143+
master_policy = var.master_policy
144+
agent_policy = var.agent_policy
145+
137146
config_path = "${path.module}/kubeconfig_${var.cluster_name}"
138147
}

example/variables.tf

+10
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ variable "jenkins_password" {
168168
default = "password"
169169
}
170170

171+
variable "agent_policy" {
172+
description = "Policy attached to Jenkins agents IAM role"
173+
default = ""
174+
}
175+
176+
variable "master_policy" {
177+
description = "Policy attached to Jenkins master IAM role"
178+
default = ""
179+
}
180+
171181
#Grafana
172182
variable "grafana_password" {
173183
description = "Password for grafana admin"

modules/cicd/jenkins/main.tf

+138
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ resource "helm_release" "jenkins" {
2525
value = "true"
2626
}
2727

28+
set {
29+
name = "serviceAccountAgent.name"
30+
value = "jenkins-agent"
31+
}
32+
33+
set {
34+
name = "serviceAccountAgent.create"
35+
value = true
36+
}
37+
38+
set_string {
39+
name = "serviceAccountAgent.annotations.eks\\.amazonaws\\.com/role-arn"
40+
value = aws_iam_role.jenkins_agent.arn
41+
}
42+
43+
set {
44+
name = "serviceAccount.name"
45+
value = "jenkins-master"
46+
}
47+
48+
set {
49+
name = "serviceAccount.create"
50+
value = true
51+
}
52+
53+
set_string {
54+
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
55+
value = aws_iam_role.jenkins_master.arn
56+
}
2857

2958
//TODO: fix it for multi domains
3059
set {
@@ -51,3 +80,112 @@ resource "helm_release" "jenkins" {
5180
file("${path.module}/values.yml")
5281
]
5382
}
83+
84+
# Enabling IAM Roles for Service Accounts
85+
data "aws_iam_policy_document" "jenkins_agent_assume_role_policy" {
86+
statement {
87+
actions = ["sts:AssumeRoleWithWebIdentity"]
88+
effect = "Allow"
89+
90+
condition {
91+
test = "StringEquals"
92+
variable = "${replace(var.cluster_oidc_url, "https://", "")}:sub"
93+
values = ["system:serviceaccount:jenkins:jenkins-agent"]
94+
}
95+
96+
principals {
97+
identifiers = [var.cluster_oidc_arn]
98+
type = "Federated"
99+
}
100+
}
101+
}
102+
103+
data "aws_iam_policy_document" "jenkins_master_assume_role_policy" {
104+
statement {
105+
actions = ["sts:AssumeRoleWithWebIdentity"]
106+
effect = "Allow"
107+
108+
condition {
109+
test = "StringEquals"
110+
variable = "${replace(var.cluster_oidc_url, "https://", "")}:sub"
111+
values = ["system:serviceaccount:jenkins:jenkins-master"]
112+
}
113+
114+
principals {
115+
identifiers = [var.cluster_oidc_arn]
116+
type = "Federated"
117+
}
118+
}
119+
}
120+
121+
# Create role for jenkins agents
122+
resource "aws_iam_role" "jenkins_agent" {
123+
depends_on = [
124+
var.module_depends_on
125+
]
126+
assume_role_policy = data.aws_iam_policy_document.jenkins_agent_assume_role_policy.json
127+
name = "${var.cluster_name}_jenkins_agent"
128+
129+
tags = {
130+
Environment = var.environment
131+
Project = var.project
132+
}
133+
}
134+
135+
# Create role for jenkins master
136+
resource "aws_iam_role" "jenkins_master" {
137+
depends_on = [
138+
var.module_depends_on
139+
]
140+
assume_role_policy = data.aws_iam_policy_document.jenkins_master_assume_role_policy.json
141+
name = "${var.cluster_name}_jenkins_master"
142+
143+
tags = {
144+
Environment = var.environment
145+
Project = var.project
146+
}
147+
}
148+
149+
# Creating agent policy
150+
resource "aws_iam_policy" "agent_policy" {
151+
count = var.agent_policy == "" ? 0 : 1
152+
depends_on = [
153+
var.module_depends_on
154+
]
155+
name = "${var.cluster_name}_agent_policy"
156+
policy = var.agent_policy
157+
}
158+
159+
# Creating master policy
160+
resource "aws_iam_policy" "master_policy" {
161+
count = var.master_policy == "" ? 0 : 1
162+
depends_on = [
163+
var.module_depends_on
164+
]
165+
name = "${var.cluster_name}_master_policy"
166+
policy = var.master_policy
167+
}
168+
169+
# Attaching agent_policy policy to role jenkins_agent
170+
resource "aws_iam_role_policy_attachment" "jenkins_agent" {
171+
count = var.agent_policy == "" ? 0 : 1
172+
depends_on = [
173+
var.module_depends_on,
174+
aws_iam_role.jenkins_agent,
175+
aws_iam_policy.agent_policy
176+
]
177+
role = aws_iam_role.jenkins_agent.name
178+
policy_arn = aws_iam_policy.agent_policy[count.index].arn
179+
}
180+
181+
# Attaching master_policy policy to role jenkins_master
182+
resource "aws_iam_role_policy_attachment" "jenkins_master" {
183+
count = var.master_policy == "" ? 0 : 1
184+
depends_on = [
185+
var.module_depends_on,
186+
aws_iam_role.jenkins_master,
187+
aws_iam_policy.master_policy
188+
]
189+
role = aws_iam_role.jenkins_master.name
190+
policy_arn = aws_iam_policy.master_policy[count.index].arn
191+
}

modules/cicd/jenkins/values.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -491,11 +491,11 @@ agent:
491491
# Raw yaml template for the Pod. For example this allows usage of toleration for agent pods.
492492
# https://github.com/jenkinsci/kubernetes-plugin#using-yaml-to-define-pod-templates
493493
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
494-
yamlTemplate: ""
495-
# yamlTemplate: |-
496-
# apiVersion: v1
497-
# kind: Pod
498-
# spec:
494+
yamlTemplate: |-
495+
apiVersion: v1
496+
kind: Pod
497+
spec:
498+
serviceAccountName: jenkins-agent
499499
# tolerations:
500500
# - key: "key"
501501
# operator: "Equal"

modules/cicd/jenkins/variables.tf

+37
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,40 @@ variable "config_path" {
1616
description = "location of the kubeconfig file"
1717
default = "~/.kube/config"
1818
}
19+
20+
#Deploy environment name
21+
variable "environment" {
22+
type = string
23+
description = "Environment Use in tags and annotations for identify EKS cluster"
24+
}
25+
26+
variable "project" {
27+
type = string
28+
description = "Project Use in tags and annotations for identify EKS cluster"
29+
}
30+
31+
variable "cluster_name" {
32+
description = "Name of the kubernetes cluster"
33+
}
34+
35+
variable "cluster_oidc_arn" {
36+
type = string
37+
description = "OIDC EKS cluster arn"
38+
default = ""
39+
}
40+
41+
variable "cluster_oidc_url" {
42+
type = string
43+
description = "OIDC EKS cluster endpoint"
44+
default = ""
45+
}
46+
47+
variable "agent_policy" {
48+
description = "Policy attached to Jenkins agents IAM role"
49+
default = ""
50+
}
51+
52+
variable "master_policy" {
53+
description = "Policy attached to Jenkins master IAM role"
54+
default = ""
55+
}

modules/system/output.tf

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ output "kubernetes_service_account" {
55
output "cert-manager" {
66
value = "${helm_release.cert-manager}"
77
}
8+
9+
output "oidc_arn" {
10+
value = "${aws_iam_openid_connect_provider.cluster.arn}"
11+
}

0 commit comments

Comments
 (0)