Preparing to deploy DevSecOps toolchains in a firewalled environment
In a secure enterprise setting, the DevOps team builds toolchains in a private hosted environment to make sure compliance, control, and automation are fully functional in a toolchain. The team streamlines the software delivery to maintain the complete ownership of their infrastructure.
During the toolchain creation and execution in a private hosted environment, the DevOps team faces integrating challenges, security management issues through the pipeline workloads.
To overcome the challenges. Follow the steps that outlines the prerequisites, configuration and permissions to create the DevSecOps solution for the Apps Stack in an IBM Cloud® account when the customers source code is hosted in a firewalled environment.
Planning and setting infrastructure
Identify your hosting environment such as on-premises data center, private cloud, or hybrid cloud, where to deploy, and how to network and secure your environment.
Installing a private worker on your infrastructure
To install the private worker, see installation of delivery pipeline private worker documentation.
Securing the environment
You need to secure the environment by using IAM, secrets manager, API keys, or encryption. Create an IBM Cloud® service API key with right permissions for Deployable Architecture (DA) creation. Refer to the permissions outlined in DevSecOps Solutions for Apps Stack.
-
Create an IBM Cloud® service API key for private worker.
-
Create an access token for connecting the source repository.
Configuring the network
The firewall must enable network connectivity between the customer environment and IBM Cloud endpoints. For more information about IBM Cloud access endpoints, see IBM Cloud endpoints.
Use Case Scenarios and application contexts
- Scenario 1: Fully Air Gapped prerequisites
- Scenario 1: Fully Air Gapped configuration
- Scenario 1: (Optional) Fully Air Gapped configuration by using a pre-existing resource group
- Scenario 1: Fully Air Gapped running of the stack
- Scenario 2: Fully Air Gapped apart from compliance pipelines
- Scenario 3: Hybrid air gapped configuration
Configuring Git triggering
You need to create and configure pipeline triggers so that events on the firewalled repositories run the correct pipeline triggers.
Following are the three triggers:
- Continuous Integration (CI) Pipeline trigger runs on application source code changes.
- Pull Request (PR) Pipeline trigger runs on merge requests on the source code repository.
- Continuous Delivery (CD) Pipeline trigger runs on merge requests on the inventory repository.
CI pipeline trigger
-
Log in to IBM Cloud console.
-
Click the Menu icon
> Platform Automation > Toolchains.
-
Click your CI toolchain >
<your CI pipeline>. -
Get the pipelineID from the URL
https://cloud.ibm.com/devops/pipelines/tekton/<CI_PIPELINE_ID>?env_id=ibm:yp:<REGION> -
Create the following JSON file,
data_push.json:{ "enabled": true, "event_listener": "ci-listener-gitlab", "filter": "header['x-gitlab-event'] == 'Push Hook' && body.ref == 'refs/heads/main'", "max_concurrent_runs": 1, "name": "Git Trigger", "secret": { "key_name": "X-Gitlab-Token", "source": "header", "type": "token_matches", "value": "<WEBHOOK_SECRET>" }, "type": "generic", "worker": { "id": "inherit" } } -
Get IBM account credentials
- Login to the IBM Cloud CLI with
ibmcloud login. - Obtain an IAM Bearer token as
IAM_TOKEN=$(ibmcloud iam oauth-tokens)
- Login to the IBM Cloud CLI with
-
Set Environment variables
IAM_TOKEN=${IAM_TOKEN:33} CI_PIPELINE_ID=36127d0b-1858-404b-b3ee-7a68aefec994 REGION=us-south -
Run the following CURL command.
`curl -X POST --location --header "Authorization: Bearer ${IAM_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" --data @data_push.json "https://api.${REGION}.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/${CI_PIPELINE_ID}/triggers"`The JSON response from the CURL command looks as shown in the code block.
{ "type": "generic", "name": "Git Trigger", "event_listener": "ci-listener-gitlab", "id": "ef110ae8-2395-4928-9dba-f80b49cab276", "filter": "header['x-gitlab-event'] == 'Push Hook' && body.ref == 'refs/heads/main'", "secret": { "type": "token_matches", "value": "hash:SHA3-512:7a4f5b0701a921c9054eb41d97258979389922592801d21d213bdb5aa99cb8aec71368153fe0a084e7c9e5be119976a8279cfa0e794de90036fe138a57e4fd31", "source": "header", "key_name": "X-Gitlab-Token" }, "properties": [], "webhook_url": "https://devops-api.us-south.devops.cloud.ibm.com/v1/tekton-webhook/f6e201e0-ba61-4e88-9a1b-6fc81febb952/run/ef110ae8-2395-4928-9dba-f80b49cab276", "max_concurrent_runs": 1, "enabled": true, "href": "https://api.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276" }
Copy the href field from the response and add the private keyword in the endpoint, as shown in the example - https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276
Creating source repository webhook for CI pipeline
You need to create a repository webhook to invoke the created trigger.
- Navigate to the webhooks page of your firewalled source code repository, for example
https://my-private-gitlab/test-admin/code-engine-compliance-app/-/hooks - Click the
Add new webhook. - Complete the URL field by using the modified
hreffield from the trigger created earlier. For example,https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276 - Choose a meaningful name. For example,
CI Pipeline webhook. - Complete the Secret
tokenwith the<WEBHOOK_SECRET>value used when creating the pipeline trigger - Select Push events > All branches as the Trigger options.
- Click Add webhook to persist your changes.
The value for the URL field can be retrieved from the trigger Webhook URL field value through the pipeline UI after the CI pipeline creation. The secret used by the webhook and trigger pair can be modified.
PR pipeline trigger
-
Log in to IBM Cloud console.
-
Click the Menu icon
> Platform Automation > Toolchains.
-
Click your PR toolchain >
<your CR pipeline>. -
Get the pipelineID from the URL. For example,
https://cloud.ibm.com/devops/pipelines/tekton/<PR_PIPELINE_ID>?env_id=ibm:yp:<REGION>. -
Create the following JSON file,
data_merge.json.{ "enabled": true, "event_listener": "pr-listener-gitlab", "filter": "header['x-gitlab-event'] == 'Merge Request Hook' && (body.object_attributes.action == 'open' || body.object_attributes.action == 'update' || body.object_attributes.action == 'reopen') && body.object_attributes.target_branch == 'main'", "max_concurrent_runs": 1, "name": "PR Git Trigger", "secret": { "key_name": "X-Gitlab-Token", "source": "header", "type": "token_matches", "value": "<WEBHOOK_SECRET>" }, "type": "generic", "worker": { "id": "inherit" } } -
Get IBM account credentials
- Login to the IBM Cloud CLI with
ibmcloud login. - Obtain an IAM Bearer token as
IAM_TOKEN=$(ibmcloud iam oauth-tokens)
- Login to the IBM Cloud CLI with
-
Set Environment variables
IAM_TOKEN=${IAM_TOKEN:33} CI_PIPELINE_ID=36127d0b-1858-404b-b3ee-7a68aefec994 REGION=us-south -
Run the following CURL command.
`curl -X POST --location --header "Authorization: Bearer ${IAM_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" --data @data_merge.json "https://api.${REGION}.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/${PR_PIPELINE_ID}/triggers"`The JSON response from the CURL command looks as shown in the code block.
{ "type": "generic", "name": "PR Git Trigger", "event_listener": "ci-listener-gitlab", "id": "ef110ae8-2395-4928-9dba-f80b49cab276", "filter": "header['x-gitlab-event'] == 'Merge Request Hook' && (body.object_attributes.action == 'open' || body.object_attributes.action == 'update' || body.object_attributes.action == 'reopen') && body.object_attributes.target_branch == 'main'", "secret": { "type": "token_matches", "value": "hash:SHA3-512:7a4f5b0701a921c9054eb41d97258979389922592801d21d213bdb5aa99cb8aec71368153fe0a084e7c9e5be119976a8279cfa0e794de90036fe138a57e4fd31", "source": "header", "key_name": "X-Gitlab-Token" }, "properties": [], "webhook_url": "https://devops-api.us-south.devops.cloud.ibm.com/v1/tekton-webhook/f6e201e0-ba61-4e88-9a1b-6fc81febb952/run/ef110ae8-2395-4928-9dba-f80b49cab276", "max_concurrent_runs": 1, "enabled": true, "href": "https://api.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276" }
Copy the href field from the response and add the private keyword in the endpoint. For example, https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276
Creating source repository webhook for PR pipeline
You need to create a repository webhook to invoke the created trigger.
- Navigate to the webhooks page of your firewalled source code repository. For example,
https://my-private-gitlab/test-admin/code-engine-compliance-app/-/hooks. - Click the
Add new webhook. - Complete the URL field using the modified
hreffield from the trigger created earlier. For example,https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276. - Choose a meaningful name. For example,
PR Pipeline webhook. - Complete the Secret
tokenwith the<WEBHOOK_SECRET>value used when creating the pipeline trigger - Select Push events > All branches as the Trigger options.
- Click Add webhook to persist your changes.
The value for the URL field can be retrieved from the trigger Webhook URL field value in the pipeline UI at any time post creation. The secret that is used by the webhook and trigger pair can be modified.
CD pipeline trigger
-
Log in to IBM Cloud console.
-
Click the Menu icon
> Platform Automation > Toolchains.
-
Click your CD toolchain >
<your CD pipeline>. -
Get the pipelineID from the URL. For example,
https://cloud.ibm.com/devops/pipelines/tekton/<CD_PIPELINE_ID>?env_id=ibm:yp:<REGION>. -
Create the following JSON file,
data_cd_merge.json:"enabled": true, "event_listener": "promotion-validation-listener-gitlab", "filter": "header['x-gitlab-event'] == 'Merge Request Hook' && (body.object_attributes.action == 'open' || body.object_attributes.action == 'reopen') && body.object_attributes.target_branch == 'prod'", "max_concurrent_runs": 1, "name": "Git Promotion Validation Trigger", "secret": { "key_name": "X-Gitlab-Token", "source": "header", "type": "token_matches", "value": "<WEBHOOK_SECRET>" }, "type": "generic", "worker": { "id": "inherit" } -
Get IBM account credentials
- Login to the IBM Cloud CLI with
ibmcloud login. - Obtain an IAM Bearer token as
IAM_TOKEN=$(ibmcloud iam oauth-tokens)
- Login to the IBM Cloud CLI with
-
Set Environment variables
IAM_TOKEN=${IAM_TOKEN:33} CI_PIPELINE_ID=36127d0b-1858-404b-b3ee-7a68aefec994 REGION=us-south -
Run the following CURL command.
`curl -X POST --location --header "Authorization: Bearer ${IAM_TOKEN}" --header "Accept: application/json" --header "Content-Type: application/json" --data @data_cd_merge.json "https://api.${REGION}.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/${CD_PIPELINE_ID}/triggers"`The JSON response from the CURL command looks as shown in the code block.
{ "type": "generic", "name": "Git Promotion Validation Trigger", "event_listener": "ci-listener-gitlab", "id": "ef110ae8-2395-4928-9dba-f80b49cab276", "filter": "header['x-gitlab-event'] == 'Merge Request Hook' && (body.object_attributes.action == 'open' || body.object_attributes.action == 'reopen') && body.object_attributes.target_branch == 'prod'", "secret": { "type": "token_matches", "value": "hash:SHA3-512:7a4f5b0701a921c9054eb41d97258979389922592801d21d213bdb5aa99cb8aec71368153fe0a084e7c9e5be119976a8279cfa0e794de90036fe138a57e4fd31", "source": "header", "key_name": "X-Gitlab-Token" }, "properties": [], "webhook_url": "https://devops-api.us-south.devops.cloud.ibm.com/v1/tekton-webhook/f6e201e0-ba61-4e88-9a1b-6fc81febb952/run/ef110ae8-2395-4928-9dba-f80b49cab276", "max_concurrent_runs": 1, "enabled": true, "href": "https://api.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276" }
Copy the href field from the response and add the private keyword. For example, https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276
Creating inventory repository webhook for CD pipeline
You need to create a repository webhook to invoke the created trigger.
- Navigate to the webhooks page of your firewalled source code repository. For example,
https://my-private-gitlab/test-admin/compliance-inventory2/-/hooks. - Click the
Add new webhook. - Complete the URL field by using the modified
hreffield from the trigger created earlier. For example,https://api.private.us-south.devops.cloud.ibm.com/pipeline/v2/tekton_pipelines/f6e201e0-ba61-4e88-9a1b-6fc81febb952/triggers/ef110ae8-2395-4928-9dba-f80b49cab276. - Choose a meaningful name. For example,
Promotion Validation webhook. - Complete the Secret
tokenwith the<WEBHOOK_SECRET>value used when creating the pipeline trigger - Select Push events > All branches as the Trigger options
- Click Add webhook to persist your changes.
The value for the URL field can be retrieved from the trigger Webhook URL field value through the pipeline UI after the CD pipeline creation. The secret that is used by the webhook and trigger pair can be modified.
Scenario 1: Fully Air Gapped prerequisites
In this scenario, you have self hosted an application repository in a private GitLab instance and all the DevSecOps compliance repositories required to operate the toolchains. For these steps the air gapped GitLab instance is referred to as
https://my-private-gitlab/ and the Git user, or owner as test-user
The required repositories can be downloaded from the following URLs. Us-south is the given example but can be replaced with any of the following: us-south, eu-gb, au-syd, eu-de, jp-tok,
jp-osa, eu-es, or ca-tor.
| URL | Description |
|---|---|
https://us-south.git.cloud.ibm.com/open-toolchain/code-engine-compliance-app |
The sample Code Engine application repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/hello-compliance-app |
The sample Kubernetes application repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/compliance-evidence-locker |
The compliance evidence repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/compliance-incident-issues |
The compliance issues repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/compliance-inventory |
The compliance inventory repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/compliance-change-management |
The compliance change management repository. |
https://us-south.git.cloud.ibm.com/open-toolchain/hello-compliance-deployment |
The sample repository containing deployment scripts. Not required when using the Code Engine sample that contains all the necessary scripts. |
https://us-south.git.cloud.ibm.com/open-toolchain/compliance-pipelines |
The compliance repository containing all the pipeline definitions. |
The repositories or the contents of the repositories need to be mirrored into the air gapped environment. For example, the URL to the sample code application is https://my-private-gitlab/test-user/code-engine-compliance-app
In this example, the repositories are set up as follows for the Code Engine application.
| URL |
|---|
https://my-private-gitlab/test-admin/code-engine-compliance-app |
https://my-private-gitlab/test-admin/compliance-evidence |
https://my-private-gitlab/test-admin/compliance-issues |
https://my-private-gitlab/test-admin/compliance-inventory |
https://my-private-gitlab/test-admin/compliance-change-management |
https://my-private-gitlab/test-admin/compliance-pipelines |
A Git personal access token is required to configure the repository tool integrations that are stood up as part of the DevSecOps toolchains and the service API key for the pipeline tool integration.
Scenario 1: Fully Air Gapped configuration
You are now ready to configure the security, required, and optional variables for an air gapped deployment by using the sample Code Engine application.
The repository URLs are specific to this example and the URLs used should reflect your environment.
- In the Configure section, select your authentication method. You can use an existing secret in Secrets Manager, add your API key directly, or set a Trusted Profile. For more information, see Using an API key or secret to authorize a project to deploy an architecture.
- In the Required tab, enter values for required fields.
- There are three region fields:
- The first declares the region in which all the services get are deployed.
- The second is for the region in which the Security and Compliance service is deployed.
- The third is for Event Notifications. By default these are set to
us-south. If you change the default, ensure that the three regions are all set the same.
- In the
app_repo_existing_urlsethttps://my-private-gitlab/test-admin/code-engine-compliance-app. - In the Optional tab, find the following variables and set the values as stated.
create_git_token- toggle totrue.repo_git_token_secret_name- set a name for your token. This is the name that appears for the Git token secret in Secrets Manager.repo_git_token_secret_value- set the Git personal access token to access the team's repositories.repo_group- set the name of the repositories group, or owner name.repo_apply_settings_to_compliance_repos-truerepo_git_provider-gitlabrepo_title- set a repository title name. For exampledevelopment server.repo_root_url- set according to your own private GitLab instance. For example,https://my-private-gitlabrepo_blind_connection-truerepo_git_id-gitlabcustomevidence_repo_existing_url-https://my-private-gitlab/test-admin/compliance-evidenceissues_repo_existing_url-https://my-private-gitlab/test-admin/compliance-issuesinventory_repo_existing_url-https://my-private-gitlab/test-admin/compliance-inventorychange_management_existing_url-https://my-private-gitlab/test-admin/compliance-change-managementcompliance_pipeline_existing_repo_url-https://my-private-gitlab/test-admin/compliance-pipelinesapp_repo_branch- Make sure that the branch name matches the branch of an example. For the Code Engine sample set asmain.create_triggers-truecreate_git_triggers-falsecompliance_pipeline_repo_use_group_settings-truecreate_privateworker_secret-trueenable_privateworker-trueprivateworker_credentials_secret_name- set a name that you would like to see the private worker secret appear as in Secrets Manager.privateworker_secret_value- Provide private worker service API key.
- Click the Save button.
Scenario 1: (Optional) Fully Air Gapped configuration using a pre-existing resource group
- Navigate to the projects level and find the current stack. Expand the stack and locate the
Compliance Managermember. Click the Options or Kebab menu. - Select Edit > Optional tab, and find the following variables and set the values as stated.
resource_group_name- Provide the name of an existing resource group in which the stack provisions the resources.use_existing_resource_group-true
- Click the Save button. Do not validate at this point.
- Navigate back up to the Projects level and find the current stack. Expand the stack and find the
Compliance Managermember. Click the Options or Kebab menu. - Select Optional tab to view the configuration of the Compliance Manager.
- Edit the
resource_groups_scopevariable, and set the name of the existing resource group in quotes within the square brackets. For example ["my-resource-group"]. - Click the Save button.
Scenario 1: Fully Air Gapped running of the stack
- Navigate to the top level of the project.
- Click the project level Manage > Settings option.
- Set
Auto-deployon to deploy all the configurations of the stack without requiring each configuration deployment to start manually. - Click the Configurations tab.
- Click the options or Kebab menu of the stack configuration to expand.
- Click **Validate and deploy to start the deployment after the validation completes.
Scenario 2: Fully Air Gapped apart from compliance pipelines
In this scenario, you can link to an existing compliance pipelines repository and allows you to always keep up to date with the latest pipeline definitions.
Otherwise, the user must periodically check the state of the repository at https://us-south.git.cloud.ibm.com/open-toolchain/compliance-pipelines and manually copy the changes to the air gapped private GitLab.
- Follow the steps as stated in Scenario 1: Fully Air Gapped configuration.
- When you get to the step of setting
compliance_pipeline_existing_repo_url, leave the value empty. - Find the input
compliance_pipeline_repo_use_group_settingsand set asfalse. - Continue the remaining steps of Scenario 1: Fully Air Gapped configuration.
Scenario 3: Hybrid air gapped configuration
In this scenario, only the repositories containing application code and scripts are stored in the private GitLab instance. The remaining compliance repositories use the default IBM Git hosted solution.
-
Follow the steps as stated in Scenario 1: Fully Air Gapped configuration.
-
When you get to the step of setting
compliance_pipeline_existing_repo_url, leave the value empty. -
Find the input
compliance_pipeline_repo_use_group_settingsand set asfalse, and leave the following variable inputs as empty.evidence_repo_existing_urlissues_repo_existing_urlinventory_repo_existing_urlchange_management_existing_url
-
Find the input
repo_apply_settings_to_compliance_reposand set asfalse. -
Continue the remaining steps of Scenario 1: Fully Air Gapped configuration.
Configuration of the Code Engine compliance app scenario 1 Name Value app_repo_branchmainapp_repo_existing_urlhttps://my-private-gitlab/test-admin/code-engine-appuse_app_repo_for_cd_deployfalse cd_deployment_repo_existing_urlhttps://my-private-gitlab/test-admin/hello-compliance-deploymentcreate_git_tokentrue create_triggerstrue create_git_triggersfalse compliance_pipeline_repo_use_group_settingstrue add_pipeline_definitionstrue create_privateworker_secrettrue enable_privateworkertrue privateworker_credentials_secret_nameprivate-worker-key privateworker_secret_value<Service-API-Key>repo_apply_settings_to_compliance_reposfalse repo_titleMy Git Enterprise Serverrepo_root_urlhttps://my-private-gitlab/repo_blind_connectiontrue repo_git_idgitlabcustomrepo_grouptest-userrepo_git_providergitlabrepo_git_token_secret_namegitlab-tokenrepo_git_token_secret_value<Access-Token>
Following are the important tips to configure the parameter in the application
-
If you are using an application repository that contains the deployment scripts such as the Code Engine then you can set
use_app_repo_for_cd_deploytotrueand leavecd_deployment_repo_existing_urlunset. -
If you already have an existing Secrets Manager instance that you need, then use
existing_secrets_manager_crn.