diff --git a/base/jenkins/jcasc_yamls/02-security-emergency.yaml b/base/jenkins/jcasc_yamls/02-security-emergency.yaml deleted file mode 100644 index 3d9286e..0000000 --- a/base/jenkins/jcasc_yamls/02-security-emergency.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# jcasc/02-security-emergency.yaml -# EMERGENCY FALLBACK - Use ONLY if LF SSO is down -# To activate: rename 02-security.yaml to 02-security-saml.yaml.bak -# rename this file to 02-security.yaml -# restart Jenkins pod: kubectl delete pod jenkins-staging-0 -n jenkins-staging -# NOTE: CSRF and disableRememberMe configs are in 02-security.yaml to avoid conflicts ---- -jenkins: - # Emergency local authentication - lf-jenkins account with static password - securityRealm: - local: - allowsSignup: false - users: - - id: "lf-jenkins" - name: "LF Jenkins Emergency Admin" - email: '${JCASC_EMERGENCY_ADMIN_EMAIL}' - password: '${JCASC_JENKINSSECURITY_ADMINPASSWORD}' - authorizationStrategy: - projectMatrix: - permissions: - # Emergency admin account - lf-jenkins only - - "Overall/Administer:lf-jenkins" - # Standard authenticated users - limited permissions - - "Overall/Read:authenticated" - - "Job/Build:authenticated" - - "Job/Cancel:authenticated" - - "Job/Read:authenticated" - - "Job/Workspace:authenticated" - - "View/Read:authenticated" diff --git a/base/jenkins/jcasc_yamls/02-security.yaml b/base/jenkins/jcasc_yamls/02-security.yaml index 11f9ec6..c24c600 100644 --- a/base/jenkins/jcasc_yamls/02-security.yaml +++ b/base/jenkins/jcasc_yamls/02-security.yaml @@ -1,47 +1,12 @@ # jcasc/02-security.yaml -# CSRF Protection: Prevents cross-site request forgery attacks -# NOTE: If automated scripts/API calls start failing with 403 errors, -# they may need to be updated to include CSRF tokens (crumbs) --- jenkins: - # Enable CSRF protection - crumbIssuer: - standard: - excludeClientIPFromCrumb: false - # Disable "Remember me" functionality for better security - # Users will need to re-authenticate after session expires - disableRememberMe: true - # SAML SSO Authentication via Linux Foundation SSO - # Emergency Access: Use 02-security-emergency.yaml if LF SSO is down securityRealm: - saml: - binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" - displayNameAttributeName: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" - emailAttributeName: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" - groupsAttributeName: "http://schemas.xmlsoap.org/claims/Group" - idpMetadataConfiguration: - period: 60 - url: "${SAML_METADATA_URL}" - logoutUrl: "${SAML_LOGOUT_URL}" - maximumAuthenticationLifetime: 86400 - usernameCaseConversion: "none" - usernameAttributeName: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" + local: + allowsSignup: false + users: + - id: "admin" + password: '${JCASC_JENKINSSECURITY_ADMINPASSWORD}' authorizationStrategy: - projectMatrix: - permissions: - # SAML Group-based Admin Access (Linux Foundation Staff) - # Security Review: Replaced hardcoded individual usernames with SAML groups - # for better maintainability and security - # 'staff': Members of the Linux Foundation staff who require full administrative access to Jenkins - - "Overall/Administer:staff" - # 'lf-releng': Members of the Linux Foundation Release Engineering team responsible for CI/CD infrastructure management - - "Overall/Administer:lf-releng" - # Emergency fallback admin account (local authentication) - - "Overall/Administer:lf-jenkins" - # Standard authenticated users - limited permissions - - "Overall/Read:authenticated" - - "Job/Build:authenticated" - - "Job/Cancel:authenticated" - - "Job/Read:authenticated" - - "Job/Workspace:authenticated" - - "View/Read:authenticated" + loggedInUsersCanDoAnything: + allowAnonymousRead: false diff --git a/base/jenkins/templates/jcasc-configmap.yaml b/base/jenkins/templates/jcasc-configmap.yaml index 519d164..34c5aa1 100644 --- a/base/jenkins/templates/jcasc-configmap.yaml +++ b/base/jenkins/templates/jcasc-configmap.yaml @@ -5,7 +5,6 @@ metadata: labels: {{- include "jenkins.labels" . | nindent 4 }} app.kubernetes.io/component: jcasc - {{ include "jenkins.fullname" . }}-jenkins-config: "true" data: {{- $files := .Files.Glob "jcasc_yamls/*.yaml" }} {{- range $path, $_ := $files }} diff --git a/base/jenkins/templates/networkpolicies.yaml b/base/jenkins/templates/networkpolicies.yaml deleted file mode 100644 index 9dd0529..0000000 --- a/base/jenkins/templates/networkpolicies.yaml +++ /dev/null @@ -1,186 +0,0 @@ -{{- if .Values.networkPolicy.enabled -}} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "jenkins.fullname" . }}-default-deny - namespace: {{ .Release.Namespace }} - labels: - {{- include "jenkins.labels" . | nindent 4 }} - app.kubernetes.io/component: network-security -spec: - podSelector: {} - policyTypes: - - Ingress - - Egress ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "jenkins.fullname" . }}-controller-ingress - namespace: {{ .Release.Namespace }} - labels: - {{- include "jenkins.labels" . | nindent 4 }} - app.kubernetes.io/component: network-security -spec: - podSelector: - matchLabels: - {{- include "jenkins.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: jenkins-controller - policyTypes: - - Ingress - ingress: - # Allow NGINX ingress controller to reach Jenkins web UI - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress - ports: - - protocol: TCP - port: 8080 - # Allow Jenkins agents to connect to controller - - from: - - podSelector: - matchLabels: - jenkins: slave - ports: - - protocol: TCP - port: 50000 - # Allow same namespace communication (config reload sidecar) - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: {{ .Release.Namespace }} - ports: - - protocol: TCP - port: 8080 ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "jenkins.fullname" . }}-controller-egress - namespace: {{ .Release.Namespace }} - labels: - {{- include "jenkins.labels" . | nindent 4 }} - app.kubernetes.io/component: network-security -spec: - podSelector: - matchLabels: - {{- include "jenkins.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: jenkins-controller - policyTypes: - - Egress - egress: - # Allow DNS resolution - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: kube-system - - podSelector: - matchLabels: - k8s-app: kube-dns - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 - # Allow Kubernetes API access - - to: [] - ports: - - protocol: TCP - port: 443 - # Allow HTTPS outbound for plugins/updates - - to: [] - ports: - - protocol: TCP - port: 443 - # Allow HTTP outbound for legacy plugins - - to: [] - ports: - - protocol: TCP - port: 80 - # Allow agent communication - - to: - - podSelector: - matchLabels: - jenkins: slave - ports: - - protocol: TCP - port: 50000 ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "jenkins.fullname" . }}-agent-ingress - namespace: {{ .Release.Namespace }} - labels: - {{- include "jenkins.labels" . | nindent 4 }} - app.kubernetes.io/component: network-security -spec: - podSelector: - matchLabels: - jenkins: slave - policyTypes: - - Ingress - ingress: - # Allow Jenkins controller to communicate with agents - - from: - - podSelector: - matchLabels: - {{- include "jenkins.selectorLabels" . | nindent 10 }} - app.kubernetes.io/component: jenkins-controller ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "jenkins.fullname" . }}-agent-egress - namespace: {{ .Release.Namespace }} - labels: - {{- include "jenkins.labels" . | nindent 4 }} - app.kubernetes.io/component: network-security -spec: - podSelector: - matchLabels: - jenkins: slave - policyTypes: - - Egress - egress: - # Allow DNS resolution - - to: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: kube-system - - podSelector: - matchLabels: - k8s-app: kube-dns - ports: - - protocol: UDP - port: 53 - - protocol: TCP - port: 53 - # Allow communication back to Jenkins controller - - to: - - podSelector: - matchLabels: - {{- include "jenkins.selectorLabels" . | nindent 10 }} - app.kubernetes.io/component: jenkins-controller - ports: - - protocol: TCP - port: 8080 - - protocol: TCP - port: 50000 - # Allow HTTPS outbound for git, docker registry, etc. - - to: [] - ports: - - protocol: TCP - port: 443 - # Allow HTTP outbound for legacy systems - - to: [] - ports: - - protocol: TCP - port: 80 - # Allow SSH for git operations - - to: [] - ports: - - protocol: TCP - port: 22 -{{- end -}} diff --git a/base/jenkins/values.yaml b/base/jenkins/values.yaml index 29f9aeb..4b33017 100644 --- a/base/jenkins/values.yaml +++ b/base/jenkins/values.yaml @@ -26,8 +26,93 @@ jenkins: JCasC: defaultConfig: false - configScripts: {} + configScripts: -# Network security configuration -networkPolicy: - enabled: true + 01-global-env-vars: | + jenkins: + globalNodeProperties: + - envVars: + env: + - key: "GLOBAL_LOG_LEVEL" + value: '${JCASC_JENKINSGLOBALENVVARS_LOGLEVEL}' + - key: "ARTIFACTORY_URL" + value: '${JCASC_JENKINSGLOBALENVVARS_ARTIFACTORYURL}' + - key: "COMPANY_NAME" + value: "OpenSearch Project" + - key: "DOCKER_REGISTRY" + value: '${JCASC_JENKINSGLOBALENVVARS_DOCKERREGISTRY}' + - key: "GIT_BASE" + value: '${JCASC_JENKINSGLOBALENVVARS_GITBASEURL}/$PROJECT' + - key: "GIT_URL" + value: '${JCASC_JENKINSGLOBALENVVARS_GITURL}' + - key: "PACKAGECLOUDPROXY" + value: '${JCASC_JENKINSGLOBALENVVARS_PACKAGECLOUDPROXY}' + - key: "PCIO_CO" + value: '${JCASC_JENKINSGLOBALENVVARS_PCIOCO}' + - key: "RELEASE_EMAIL" + value: '${JCASC_JENKINSGLOBALENVVARS_RELEASEEMAIL}' + - key: "RELEASE_USERNAME" + value: '${JCASC_JENKINSGLOBALENVVARS_RELEASEUSERNAME}' + - key: "S3_BUCKET" + value: '${JCASC_JENKINSGLOBALENVVARS_S3BUCKET}' + - key: "CDN_URL" + value: '${JCASC_JENKINSGLOBALENVVARS_CDNURL}' + - key: "SIGUL_KEY" + value: '${JCASC_JENKINSGLOBALENVVARS_SIGULKEY}' + - key: "SILO" + value: '${JCASC_JENKINSGLOBALENVVARS_SILO}' + + 02-security: | + jenkins: + securityRealm: + local: + allowsSignup: false + users: + - id: "admin" + password: '${JCASC_JENKINSSECURITY_ADMINPASSWORD}' + authorizationStrategy: + loggedInUsersCanDoAnything: + allowAnonymousRead: false + + 03-tools: | + tool: + jdk: + installations: + - name: "jdk-17" + home: "/opt/java/openjdk" + git: + installations: + - name: "Default" + home: "git" + + 04-global-libraries: | + # Jenkins global pipeline library configurations placeholder + + 05-plugins-config: | + unclassified: + gitHubConfiguration: + apiRateLimitChecker: ThrottleForNormalize + gitHubPluginConfig: + configs: + - name: "opensearch-project" + credentialsId: "github-api-token-placeholder" + hookUrl: "http://jenkins.placeholder.example.com/github-webhook/" + ghprbTrigger: + cron: "H/5 * * * *" + githubAuth: + - id: "opensearch-project-ghprb-auth" + serverAPIUrl: "https://api.github.com" + credentialsId: "github-api-token-placeholder" + description: "GitHub auth for opensearch-project PR builder" + adminlist: "" + manageWebhooks: false + okToTestPhrase: ".*ok to test.*" + retestPhrase: ".*test this please.*" + skipBuildPhrase: ".*\\[skip ci\\].*" + + 06-credentials: | + # Jenkins credential configurations placeholder + + 07-cloud-agents: | + # Cloud agents configuration moved to separate jcasc_yamls file + # See: base/jenkins/jcasc_yamls/07-cloud-agents.yaml diff --git a/build/Dockerfile b/build/Dockerfile index ff847f1..65f35a0 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -7,11 +7,11 @@ ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false # Copy the plugins.txt file COPY plugins.txt /usr/share/jenkins/ref/plugins.txt -# Switch to root only for essential system package installations +# Switch to root for install USER root -# Install system packages with security best practices -RUN apt-get update && apt-get install -y --no-install-recommends \ +# Install system packages and dependencies +RUN apt-get update && apt-get install -y \ curl \ wget \ git \ @@ -19,7 +19,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3 \ python3-pip \ python3-dev \ - python3-venv \ zip \ unzip \ build-essential \ @@ -27,45 +26,24 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ gnupg \ lsb-release \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean \ - && apt-get autoremove -y + && rm -rf /var/lib/apt/lists/* -# Install Docker CLI with GPG verification +# Install Docker CLI (for containerized builds) RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \ && apt-get update \ - && apt-get install -y --no-install-recommends docker-ce-cli \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean + && apt-get install -y docker-ce-cli \ + && rm -rf /var/lib/apt/lists/* -# Install GitHub CLI with GPG verification +# Install GitHub CLI RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ && apt-get update \ - && apt-get install -y --no-install-recommends gh \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean + && apt-get install -y gh \ + && rm -rf /var/lib/apt/lists/* -# Install Node.js 18.x (maintained as root for system-wide installation) -RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Install global npm packages as root (for system-wide access) -RUN npm install -g fs-extra chalk@4.1.2 aws-cdk cdk-assume-role-credential-plugin@1.4.0 - -# Create jenkins directories with proper permissions while root -RUN mkdir -p /var/jenkins /home/jenkins/.local /home/jenkins/.local/bin \ - && chown -R jenkins:jenkins /var/jenkins /home/jenkins/.local - -# Switch to jenkins user as early as possible -USER jenkins - -# Install Python packages as jenkins user with venv -RUN python3 -m venv /home/jenkins/.local/venv \ - && /home/jenkins/.local/venv/bin/pip install --no-cache-dir \ +# Install Python packages used by OpenSearch +RUN pip3 install --no-cache-dir --break-system-packages \ boto3 \ pyyaml \ requests==2.32.0 \ @@ -74,20 +52,24 @@ RUN python3 -m venv /home/jenkins/.local/venv \ pipenv \ awscli -# Add virtual environment to PATH for Python packages -ENV PATH="/home/jenkins/.local/venv/bin:/home/jenkins/.local/bin:${PATH}" +# Install Node.js 18.x and global npm packages (system-wide installation) +RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get install -y nodejs \ + && npm install -g fs-extra chalk@4.1.2 aws-cdk cdk-assume-role-credential-plugin@1.4.0 \ + && rm -rf /var/lib/apt/lists/* + +# Install 1Password CLI using main branch +RUN curl -SfL https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/ci/config/op-setup.sh -o op-setup.sh && \ + bash op-setup.sh && \ + rm -v op-setup.sh -# Install 1Password CLI (requires root temporarily) -USER root -RUN curl -SfL https://raw.githubusercontent.com/opensearch-project/opensearch-build/main/docker/ci/config/op-setup.sh -o op-setup.sh \ - && bash op-setup.sh \ - && rm -v op-setup.sh \ - && chown jenkins:jenkins /usr/local/bin/op 2>/dev/null || true +# Create jenkins directories with proper permissions +RUN mkdir -p /var/jenkins && chown -R jenkins:jenkins /var/jenkins -# Return to jenkins user immediately after privileged operation +# Switch back to jenkins user USER jenkins -# Install Jenkins plugins as jenkins user +# Install Jenkins plugins RUN jenkins-plugin-cli --verbose --plugin-file /usr/share/jenkins/ref/plugins.txt # Verify installations work diff --git a/build/plugins.txt b/build/plugins.txt index 8b6d64c..e2ad79b 100644 --- a/build/plugins.txt +++ b/build/plugins.txt @@ -38,7 +38,6 @@ ldap lockable-resources login-theme managed-scripts -matrix-auth nodelabelparameter nvm-wrapper oic-auth diff --git a/dev/values.yaml b/dev/values.yaml index 49a6eb1..b295b74 100644 --- a/dev/values.yaml +++ b/dev/values.yaml @@ -35,8 +35,6 @@ jenkinsEnvVars: JCASC_SYSTEM_MESSAGE: "Welcome to Jenkins (Development Environment)" JCASC_LOCATION_URL: "" JCASC_LOCATION_ADMINADDRESS: "dev-admin@example.com" - # Emergency Admin Email (used in 02-security-emergency.yaml) - JCASC_EMERGENCY_ADMIN_EMAIL: "dev-admin@example.com" JCASC_MASTER_LABELS: "dev-master local" JCASC_RESOURCE_ROOT_URL: "" JCASC_DISABLE_DEFERRED_WIPEOUT: "false" diff --git a/production/values.yaml b/production/values.yaml index d97ba5a..f44fbf7 100644 --- a/production/values.yaml +++ b/production/values.yaml @@ -25,8 +25,6 @@ jenkins: JCASC_SYSTEM_MESSAGE: "Welcome to Jenkins (Production Environment)" JCASC_LOCATION_URL: "" JCASC_LOCATION_ADMINADDRESS: "releng+opensearch-jenkins@linuxfoundation.org" - # Emergency Admin Email (used in 02-security-emergency.yaml) - JCASC_EMERGENCY_ADMIN_EMAIL: "releng+opensearch-jenkins@linuxfoundation.org" JCASC_MASTER_LABELS: "prod-controller" JCASC_RESOURCE_ROOT_URL: "" JCASC_DISABLE_DEFERRED_WIPEOUT: "false" diff --git a/staging/values.yaml b/staging/values.yaml index 8e7385f..1602da2 100644 --- a/staging/values.yaml +++ b/staging/values.yaml @@ -19,25 +19,12 @@ jenkins: # Environment variables for Jenkins container (JCasC configuration) containerEnv: - # JCasC Configuration Path Override (fix for image default mismatch) - - name: CASC_JENKINS_CONFIG - value: "/var/jenkins_home/casc_configs" - # Security Configuration - - name: JCASC_JENKINSSECURITY_ADMINPASSWORD - valueFrom: - secretKeyRef: - name: jenkins-staging - key: jenkins-admin-password - # System Configuration - name: JCASC_SYSTEM_MESSAGE value: "Welcome to Jenkins (Staging Environment)" - name: JCASC_LOCATION_URL - value: "https://jenkins-stag.opensearch.cluster.linuxfound.info" + value: "" - name: JCASC_LOCATION_ADMINADDRESS value: "releng+opensearch-jenkins@linuxfoundation.org" - # Emergency Admin Email (used in 02-security-emergency.yaml) - - name: JCASC_EMERGENCY_ADMIN_EMAIL - value: "releng+opensearch-jenkins@linuxfoundation.org" - name: JCASC_MASTER_LABELS value: "staging-controller" - name: JCASC_RESOURCE_ROOT_URL @@ -99,12 +86,6 @@ jenkins: - name: JCASC_JENKINSGLOBALENVVARS_SILO value: "staging" - # SAML Configuration - - name: SAML_METADATA_URL - value: "https://sso.linuxfoundation.org/samlp/metadata/Sa8MIoI91JUE3154tjDzTATsEeiehGaZ" - - name: SAML_LOGOUT_URL - value: "https://sso.linuxfoundation.org/samlp/Sa8MIoI91JUE3154tjDzTATsEeiehGaZ/logout" - # Kubernetes Cloud Configuration - name: JCASC_KUBERNETES_URL value: "https://kubernetes.default.svc.cluster.local"