CICD deployment in conditions of limited access (Go language)
Tags: go, cicd, aws, backenddevelopment
Published: 2024-02-15 21:40:28

In an environment with increased requirements for information security, a situation is possible when the CICD runner does not have access to external resources: the Docker image repository (for example, public.ecr.aws), external dependency packages, etc. In such conditions, I suggest the following actions (examples of the Go language):

## Image problem:

We create a Docker image that meets our requirements (let it be minimal, golang 1.21 + AWS CDK based on Alpine):

```
FROM golang:1.21-alpine

RUN apk update && apk add --update --no-cache \
git \
bash \
nodejs \
npm
RUN npm update -g
# Install AWSCDK
RUN npm install -g
RUN cdk --version
ENTRYPOINT []
```

Build your image:
`docker build --network host -t go-cdk-image .`

Let's look at the result, and get the ID of the image:

```
docker images
REPOSITORY TAG IMAGE
ID CREATED SIZE
go-cdk-image latest f93a28e7b39a 2 hours ago 324MB
```
Adding a tag:
`docker tag f93a28e7b39a 1234567890.dkr.ecr.eu-central-1.amazonaws.com/golang-cdk-image:latest`

Add credentials, if not created (File: **_./aws/config_**):

```
[profile mydevprofile]
sso_start_url = https://my-auth.awsapps.com/start
sso_region = eu-west-1
sso_account_id = 1234567890
sso_role_name = infosec-full
region = eu-central-1
output = json
```

Login using SSO:
`aws sso login --profile mydevprofile`

Logging in to the AWS elastic container registry:

```
aws ecr get-login-password --region eu-central-1 --profile mydevprofile | docker login --username AWS --passwordstdin
1234567890.dkr.ecr.eu-central-1.amazonaws.com
```

Pushing the image:
`docker push 1234567890.dkr.ecr.eu-central-1.amazonaws.com/golang-cdk-image:latest`

Thus, at the moment, this Docker image is available within the corporate AWS in conditions of blocked internet. It is possible to use it in the pipeline by adding to **_.gitlab-ci.yml_**
`image: 989668876111.dkr.ecr.eu-central-1.amazonaws.com/golang-cdk-image:latest`

For cross-account use, you need to configure additional access rights to the downloaded image.

## Working with dependencies

To work with dependencies, we will use the Golang module vendoring mechanism.
In the CICD config .gitlab-ci.yml we add (in the script section):

```
script:
 - export GO111MODULE=on

```
Also, we can add here the **GOFLAGS=-mod=vendor** option, but we can do this in the code as well.

```
lambdaFunction := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("BackendLambda"),
		&awscdklambdagoalpha.GoFunctionProps{
			// Fill all the necessary attributes here...
			Bundling: &awscdklambdagoalpha.BundlingOptions{
				GoBuildFlags: jsii.Strings(`-ldflags "-s -w" -mod=vendor`), //see here
			},
		})
```

In the root folder of the project we should execute:

```
go mod init my-progect-name
go mod tidy
go mod vendor
```

The go.mod and go.sum files will be created, as well as the vendor directory with all dependencies. These artifacts should also be included in the git commit.

## Nota bene!

It seems that everything is ready, but there is one important point related to the options of the AWS CDK Golang itself. If we look at the code of the **cdk.json** file, which the CDK created automatically, we see the following code:

```
{
  "app": "go mod download && go run backend-lambda2.go", // see here!
  "watch": {
    "include": [
      "**"
    ],
    "exclude": [
      "README.md",
      "cdk*.json",
      "go.mod",
      "go.sum",
      "**/*test.go"
    ]
  }
}
```

The code **go mod download && go run backend-lambda2.go** destroys the scheme and forces work with the internet.
That is, our last action is to change the code to go run **backend-lambda2.go**, excluding **go mod download**.
Now, when performing a git push, our pipeline will work even in conditions of limited access.

Congrats, it works!