Skip to content

Instantly share code, notes, and snippets.

@waltervargas
Created January 29, 2018 07:41
Show Gist options
  • Save waltervargas/3961b056058ec8af71766b387e04ec42 to your computer and use it in GitHub Desktop.
Save waltervargas/3961b056058ec8af71766b387e04ec42 to your computer and use it in GitHub Desktop.
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Jenkins Bootstrapping Template
Metadata:
Version: '0.0.1'
Stack: 0
AWS::CloudFormation::Interface:
ParameterGroups:
- Parameters:
- StackPrefix
Label:
default: Tagging
- Parameters:
- GitUrl
- GitBranch
- InstanceType
- Key
- Plugins
- Bucket
Label:
default: Jenkins
Mappings:
RegionMap:
us-west-1:
"amazon": "ami-7690240f"
Parameters:
InstanceType:
Description: Instance Type for Jenkins
ConstraintDescription: Please provide a valid Amazon EC2 Instance Type
Type: String
Default: m3.large
AllowedValues:
- t2.medium
- m3.medium
- m3.large
Key:
ConstraintDescription: Please provide a valid Amazon EC2 Key Pair Name
Type: AWS::EC2::KeyPair::KeyName
Description: Amazon EC2 Key Pair Name
Plugins:
Default: job-dsl git github workflow-aggregator pipeline-stage-view docker-custom-build-environment jenkins-multijob-plugin ansicolor
ConstraintDescription: Please provide a list of valid Jenkins plugins names
Type: String
Description: Jenkins plugins id (space separator).
JenkinsBucket:
Type: String
Description: Jenkins Backup and Restore S3 Bucket.
Restore:
Default: false
Type: String
Description: Restore Jenkins from last backup?
AllowedValues:
- true
- false
GitUrl:
ConstraintDescription: Please provide a git url.
Type: String
Description: Git Repository for IAC.
GitBranch:
Default: master
ConstraintDescription: Must be a valid git branch
Type: String
Description: Git Branch
AllowFromCIDR:
Type: String
Description: Allow access from this ip address
ConstraintDescription: Please Provides a valid CIDR Block.
Resources:
JenkinsS3AccessPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Path: !Sub "/${AWS::StackName}/Jenkins/S3AccessPolicy/"
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action:
- s3:*
Resource:
- !Sub "arn:aws:s3:::${Bucket}/*"
-
Effect: Deny
Action:
- s3:Delete*
- s3:*Acl*
Resource:
- !Sub "arn:aws:s3:::${Bucket}"
SeedJenkinsInstanceRole:
Type: AWS::IAM::Role
Properties:
Path: !Sub "/${StackPrefix}/JenkinsInstanceRole/"
ManagedPolicyArns:
- Ref: SeedJenkinsAccessPolicy
- Ref: SeedS3AccessPolicy
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
SeedJenkinsInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: !Sub "/${StackPrefix}/JenkinsInstanceProfile/"
Roles:
- Ref: SeedJenkinsInstanceRole
JenkinsSG:
Type: AWS::EC2::SecurityGroup
Properties:
Tags:
- Value: !Sub ${StackPrefix}
Key: Prefix
- Value: !Sub ${StackPrefix}-JenkinsSG
Key: Name
GroupDescription: Jenkins Security Group
SecurityGroupIngress:
- ToPort: '22'
FromPort: '22'
IpProtocol: tcp
CidrIp: !Sub ${AllowFromIP}
- ToPort: '8080'
FromPort: '8080'
IpProtocol: tcp
CidrIp: !Sub ${AllowFromIP}
JenkinsSeedLc:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", amazon]
KeyName:
Ref: JenkinsKey
SecurityGroups:
- Ref: JenkinsSG
IamInstanceProfile:
Ref: SeedJenkinsInstanceProfile
InstanceType:
Ref: JenkinsInstanceType
UserData:
Fn::Base64: !Sub |
#!/bin/bash
# Update route53 record
localip=$(curl -fs http://169.254.169.254/latest/meta-data/local-ipv4)
echo "$localip jenkins" >> /etc/hosts
hostname jenkins
yum update -y
yum install -y aws-cfn-bootstrap docker jq perl-Test-Simple.noarch perl-YAML.noarch
# docker
service docker start
chkconfig docker on
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource JenkinsSeedLc --configsets jenkins --region ${AWS::Region}
Metadata:
AWS::CloudFormation::Init:
configSets:
jenkins:
- "jenkins_setup"
jenkins_setup:
files:
/etc/yum.repos.d/jenkins.repo:
content: |
[jenkins]
name=Jenkins
baseurl=http://pkg.jenkins.io/redhat
gpgcheck=1
owner: "root"
group: "root"
mode: "000644"
/tmp/jenkins-security.groovy:
content: !Sub |
#!groovy
import hudson.security.*
import jenkins.model.*
def instance = Jenkins.getInstance()
def JenkinsPass = System.getenv("JenkinsAdminPassword")
println "--> Checking if security has been set already"
if (!instance.isUseSecurity()) {
println "--> creating local user 'admin'"
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount('${JenkinsAdminUser}', JenkinsPass)
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
}
owner: "root"
group: "root"
mode: "000744"
/tmp/plugins.groovy:
content: !Sub |
#!groovy
import jenkins.model.*
import java.util.logging.Logger
def log = Logger.getLogger("")
def instance = Jenkins.getInstance()
def updateCenter = instance.getUpdateCenter()
def pluginManager = instance.getPluginManager()
def plugins = "${JenkinsPlugins}".split()
def plugins_installed = false
log.info("" + plugins)
updateCenter.updateAllSites()
plugins.each {
log.info("plugin: " + it)
if (!pluginManager.getPlugin(it)) {
def plugin = updateCenter.getPlugin(it)
if (plugin){
plugin.deploy()
plugins_installed = true
log.info("Installing plugin " + it)
}
}
}
if (plugins_installed){
instance.save()
instance.doSafeRestart()
}
owner: "root"
group: "root"
mode: "000744"
/tmp/aseed-job:
content: !Sub |
def GIT_URL='${GitUrl}'
def GIT_BRANCH='${GitBranch}'
def DEVOPS_BUCKET='${JenkinsBackupBucket}'
def DEVOPS_BUCKET_DR='${JenkinsBackupBucket}-dr'
job('seed-job') {
description('Seed Job')
parameters {
stringParam('GIT_URL', GIT_URL, 'Repo URL')
stringParam('GIT_BRANCH', GIT_BRANCH, 'Git Branch')
stringParam('DEVOPS_BUCKET', DEVOPS_BUCKET, 'DEVOPS Bucket')
stringParam('DEVOPS_BUCKET_DR', DEVOPS_BUCKET_DR, 'Git Branch')
}
scm {
git('\${!GIT_URL}', '\${!GIT_BRANCH}')
}
triggers {
scm('H/15 * * * *')
}
steps {
dsl {
external "jenkins-jobs/**/*.groovy"
}
}
}
owner: "root"
group: "root"
mode: "000744"
/tmp/disable-script-security-dsl.groovy:
content: !Sub |
import javaposse.jobdsl.plugin.GlobalJobDslSecurityConfiguration
import jenkins.model.GlobalConfiguration
import org.kohsuke.stapler.StaplerRequest
// current value
println GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).useScriptSecurity
// change vaue
StaplerRequest stapler = null
net.sf.json.JSONObject jsonObject = new net.sf.json.JSONObject()
//jsonObject.put("useScriptSecurity", false) // it uses has method https://github.com/jenkinsci/job-dsl-plugin/blob/6a70bba91e671ebe72fd682e92e9abea48a2b050/job-dsl-plugin/src/main/groovy/javaposse/jobdsl/plugin/GlobalJobDslSecurityConfiguration.groovy#L21
GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).configure(stapler, jsonObject)
// new value
println GlobalConfiguration.all().get(GlobalJobDslSecurityConfiguration.class).useScriptSecurity
/tmp/zz-load-seed-job.groovy:
content: !Sub |
import javaposse.jobdsl.dsl.DslScriptLoader
import javaposse.jobdsl.plugin.JenkinsJobManagement
def jobDslScript = new File('/tmp/aseed-job')
def workspace = new File('.')
def jobManagement = new JenkinsJobManagement(System.out, [:], workspace)
new DslScriptLoader(jobManagement).runScript(jobDslScript.text)
owner: "root"
group: "root"
mode: "000744"
/tmp/gitconfig:
content: |
[user]
name = Jenkins Master
email = jenkins@jenkins
owner: "root"
group: "root"
mode: "000744"
commands:
command_01:
command: |
# Update java version required by Jenkins
yum remove -y java-1.7.0-openjdk
yum install -y java-1.8.0
rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
yum -y install jenkins git
usermod -a -G jenkins ec2-user
usermod -a -G docker jenkins
command_02:
command: |
echo JENKINS_JAVA_OPTIONS=\"-Djava.awt.headless=true -Djenkins.install.runSetupWizard=false\" >> /etc/sysconfig/jenkins
# Add jenkins user to sudoers and disable tty
echo "jenkins ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
echo "Defaults:%jenkins !requiretty" >> /etc/sudoers
echo "Defaults:jenkins !requiretty" >> /etc/sudoers
command_03:
command: !Sub |
echo "export JenkinsAdminPassword=`aws --region ${AWS::Region} ssm get-parameters --name stack.service.vpc-jenkins.JenkinsAdminPassword --with-decryption --output text | cut -f 4 `" >> /etc/sysconfig/jenkins
source /etc/sysconfig/jenkins
mkdir $JENKINS_HOME/init.groovy.d 2> /dev/null
cp -v /tmp/*.groovy $JENKINS_HOME/init.groovy.d/ 2> /dev/null
cp /tmp/gitconfig $JENKINS_HOME/.gitconfig
chown -R jenkins $JENKINS_HOME/init.groovy.d/
service jenkins start
chkconfig jenkins on
command_04:
command: !Sub |
# Generate ssh deployment key
source /etc/sysconfig/jenkins
instanceid=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
su -c "ssh-keygen -b 1024 -t rsa -N '' -f $JENKINS_HOME/.ssh/id_rsa" jenkins -s /bin/bash
pubkey=$(cat $JENKINS_HOME/.ssh/id_rsa.pub)
aws ec2 create-tags --resource $instanceid --tags Key=deploykey,Value="$pubkey" --region ${AWS::Region}
echo "StrictHostKeyChecking no" >> $JENKINS_HOME/.ssh/config
echo "UserKnownHostsFile /dev/null" >> $JENKINS_HOME/.ssh/config
command_05:
command: !Sub |
source /etc/sysconfig/jenkins
if [[ ${JenkinsRestore} == true ]];
then
devops_bucket_content=`aws s3 ls s3://${JenkinsBackupBucket}/backups/jenkins/`
if [[ $devops_bucket_content == "" ]];
then
echo "No backups available";
else
wget http://localhost:8080/jnlpJars/jenkins-cli.jar -NqO /opt/jenkins-cli.jar
aws s3 sync --region ${AWS::Region} s3://${JenkinsBackupBucket}/backups/jenkins/ /var/lib/jenkins/
chown -R jenkins:jenkins /var/lib/jenkins
chmod 600 /var/lib/jenkins/.ssh/id_rsa
find /var/lib/jenkins/jobs/ -name "last*" -exec rm -rf '{}' \;
sleep 10
java -jar /opt/jenkins-cli.jar -s http://localhost:8080 restart --username ${JenkinsAdminUser} --password $JenkinsAdminPassword
pubkey=$(cat $JENKINS_HOME/.ssh/id_rsa.pub)
instanceid=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ec2 create-tags --resource $instanceid --tags Key=deploykey,Value="$pubkey" --region ${AWS::Region}
fi
fi
## Removing Jenkins admin password from the ENV
sed -i 's/^export JenkinsAdminPassword.*$//g' /etc/sysconfig/jenkins
JenkinsASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
DesiredCapacity: 1
Tags:
- PropagateAtLaunch: 'true'
Value: !Sub "${StackPrefix}"
Key: StackPrefix
- PropagateAtLaunch: 'true'
Value: !Sub "${StackPrefix}-jenkins"
Key: Name
MinSize: 1
MaxSize: 1
LaunchConfigurationName:
Ref: JenkinsSeedLc
HealthCheckGracePeriod: '600'
HealthCheckType: EC2
AvailabilityZones:
Fn::GetAZs: ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment