diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml new file mode 100644 index 0000000..935bfe1 --- /dev/null +++ b/.github/workflows/cd.yaml @@ -0,0 +1,116 @@ +--- +# Prerequisites: +# +# * terraform/aws/aws-github-oidc - to provide ability to assume AWS role via GitHub Action OIDC provider +name: CD + +on: + workflow_run: + workflows: ["CI"] + types: [completed] + branches: [main] + + workflow_dispatch: + inputs: + runner: + description: 'Runner type' + required: true + default: 'ubuntu-24.04' + type: choice + options: + - ubuntu-24.04 + - matihost + env: + description: 'Target environment' + required: true + default: 'dev' + type: environment + mode: + description: 'Deployment mode' + required: true + default: 'plan' + type: choice + options: + - plan + - apply + - destroy + module: + description: 'Module to deploy' + required: true + default: 'aws/aws-site' +permissions: + contents: read + id-token: write +concurrency: + group: aws-${{ github.ref }}-${{ inputs.env || 'dev' }} + cancel-in-progress: false +env: + DEPLOY_ENV: ${{ inputs.env || 'dev' }} + DEPLOY_MODE: ${{ inputs.mode || 'plan' }} +jobs: + sources: + name: Checkout + + if: ${{ github.event.workflow_run.conclusion == 'success' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + timeout-minutes: 5 + container: + image: quay.io/matihost/cd + outputs: + GIT_COMMIT_HASH: ${{ steps.git_hash.outputs.GIT_COMMIT_HASH }} + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + fetch-depth: 0 + # Workaround for https://github.com/actions/runner/issues/2033 + - name: Set ownership + run: | + chown -R $(id -u):$(id -g) $PWD + - name: Obtain git version + id: git_hash + run: | + echo "GIT_COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + - name: Cache workspace + uses: actions/cache/save@v4 + with: + # avoid using github.workspace in caching? + # so how effectivelly share source code between jobs? + # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cross-os-cache + # artifacts? + # cleaning artifacts after workflow requires custom, non standard action: + # https://github.com/marketplace/actions/delete-artifact + path: ${{ github.workspace }} + key: sources-${{ github.run_id }}-${{ github.run_attempt }} + enableCrossOsArchive: true + aws: + name: AWS deployment of ${{ inputs.module || 'aws/aws-site'}} on ${{ inputs.env || 'dev' }} environment + needs: sources + environment: ${{ inputs.env || 'dev' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + timeout-minutes: 30 + container: + image: quay.io/matihost/cd + steps: + - name: Download sources + uses: actions/cache/restore@v4 + with: + path: ${{ github.workspace }} + key: sources-${{ github.run_id }}-${{ github.run_attempt }} + fail-on-cache-miss: true + enableCrossOsArchive: true + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: us-east-1 + role-to-assume: ${{ secrets.AWS_OIDC_ASSUMED_ROLE }} + role-session-name: gh-${{ inputs.env || 'dev' }}-aws@monorepo@matihost-${{ github.run_id }}-${{ github.run_attempt }} + - name: Deployment + working-directory: "terraform/${{ inputs.module || 'aws/aws-site'}}" + env: ${{ secrets }} + # env: + # TLS_CRT: "${{ secrets.TLS_CRT }}" + # TLS_CHAIN: "${{ secrets.TLS_CHAIN }}" + # TLS_KEY: "${{ secrets.TLS_KEY }}" + run: |- + make run ENV=${{env.DEPLOY_ENV}} MODE=${{ env.DEPLOY_MODE }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 23d586b..d45cbf4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,10 +16,10 @@ on: runner: description: 'Runner type' required: true - default: 'ubuntu-22.04' + default: 'ubuntu-24.04' type: choice options: - - ubuntu-22.04 + - ubuntu-24.04 - matihost schedule: - cron: '27 20 * * 0' @@ -37,7 +37,7 @@ env: jobs: sources: name: Checkout sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 5 container: image: maven:3-eclipse-temurin-21 @@ -70,7 +70,7 @@ jobs: enableCrossOsArchive: true java: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: image: maven:3-eclipse-temurin-21 @@ -116,10 +116,10 @@ jobs: enableCrossOsArchive: true java-image-mq-app: needs: java - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/java-ci steps: - name: Download java build sources uses: actions/cache/restore@v4 @@ -131,7 +131,7 @@ jobs: - name: Build Java mq client image working-directory: java/apps/mq/client env: - container: "${{ inputs.runner == 'ubuntu-22.04' && 'docker' || 'kube' }}" + container: "${{ inputs.runner == 'ubuntu-24.04' && 'docker' || 'kube' }}" REGISTRY: "${{ vars.REGISTRY || 'quay.io' }}" REGISTRY_USER: "${{ secrets.REGISTRY_USER }}" REGISTRY_PASSWORD: "${{ secrets.REGISTRY_PASSWORD }}" @@ -144,10 +144,10 @@ jobs: --destination="${{ env.REGISTRY }}/matihost/mq/basic-client:${{ env.IMAGE_TAG }}" java-image-cmdline: needs: java - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/java-ci steps: - name: Download java build sources uses: actions/cache/restore@v4 @@ -159,7 +159,7 @@ jobs: - name: Build Java command-line image working-directory: java/apps/command-line env: - container: "${{ inputs.runner == 'ubuntu-22.04' && 'docker' || 'kube' }}" + container: "${{ inputs.runner == 'ubuntu-24.04' && 'docker' || 'kube' }}" REGISTRY: "${{ vars.REGISTRY || 'quay.io' }}" REGISTRY_USER: "${{ secrets.REGISTRY_USER }}" REGISTRY_PASSWORD: "${{ secrets.REGISTRY_PASSWORD }}" @@ -173,7 +173,7 @@ jobs: --destination="${{ env.REGISTRY }}/matihost/commandline:${{ env.IMAGE_TAG }}" codeql-java: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: image: maven:3-eclipse-temurin-21 @@ -206,7 +206,7 @@ jobs: category: "/language:java" codeql-go: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: golang:1.22 env: @@ -241,7 +241,7 @@ jobs: category: "/language:go" codeql-python: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: image: quay.io/matihost/ansible:root @@ -275,7 +275,7 @@ jobs: category: "/language:python" ansible: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: image: quay.io/matihost/ansible:root @@ -292,7 +292,7 @@ jobs: working-directory: ansible/learning rust: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: image: rust @@ -308,11 +308,11 @@ jobs: working-directory: rust/guessing_game image-build-on-gcp-artifact-registry: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} - if: ((inputs.runner || 'ubuntu-22.04') != 'ubuntu-22.04') && vars.GCP_PROJECT + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + if: ((inputs.runner || 'ubuntu-24.04') != 'ubuntu-24.04') && vars.GCP_PROJECT timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/java-ci steps: - name: Download sources uses: actions/cache/restore@v4 @@ -333,11 +333,11 @@ jobs: --destination="gcr.io/${{ env.GCP_PROJECT }}/ansible:${{ env.GIT_COMMIT_HASH }}" image-build-generic-registry: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} if: vars.REGISTRY timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/java-ci steps: - name: Download sources uses: actions/cache/restore@v4 @@ -360,10 +360,10 @@ jobs: --destination="${{ env.REGISTRY }}/matihost/ansible:${{ env.IMAGE_TAG }}" image-build-ghcr: needs: sources - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/java-ci steps: - name: Download sources uses: actions/cache/restore@v4 @@ -375,7 +375,7 @@ jobs: - name: Build Ansible image on GH hosted runner with deployment to GH Packages working-directory: k8s/images/ansible env: - container: "${{ inputs.runner == 'ubuntu-22.04' && 'docker' || 'kube' }}" + container: "${{ inputs.runner == 'ubuntu-24.04' && 'docker' || 'kube' }}" run: | mkdir -p /kaniko/.docker AUTH=$(echo -n ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} | base64) diff --git a/.github/workflows/gcp.yaml b/.github/workflows/gcp.yaml index 274abd7..5729bbe 100644 --- a/.github/workflows/gcp.yaml +++ b/.github/workflows/gcp.yaml @@ -14,10 +14,10 @@ on: runner: description: 'Runner type' required: true - default: 'ubuntu-22.04' + default: 'ubuntu-24.04' type: choice options: - - ubuntu-22.04 + - ubuntu-24.04 - matihost env: description: 'Target environment' @@ -38,11 +38,11 @@ env: jobs: gcp: name: Run GCP related tasks - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} environment: ${{ inputs.env || 'dev' }} timeout-minutes: 30 container: - image: quay.io/matihost/gh-gcp-java-kaniko + image: quay.io/matihost/cd permissions: contents: 'read' id-token: 'write' @@ -97,7 +97,7 @@ jobs: --destination="${GAR_LOCATION}-docker.pkg.dev/${GCP_PROJECT}/${GAR_REPOSITORY}/ansible:${{ env.IMAGE_TAG }}" - name: Set up GKE credentials uses: google-github-actions/get-gke-credentials@v2 - if: ((inputs.runner || 'ubuntu-22.04') != 'ubuntu-22.04') + if: ((inputs.runner || 'ubuntu-24.04') != 'ubuntu-24.04') with: cluster_name: ${{ env.GKE_CLUSTER }} location: ${{ env.GKE_LOCATION }} @@ -105,6 +105,6 @@ jobs: - name: Run kubectl # when run on self-hosted runner within GCP network, otherwise cluster is not accessible from internet # TODO consider add https://api.github.com/meta actions servers to authz GKE networks... - if: ((inputs.runner || 'ubuntu-22.04') != 'ubuntu-22.04') + if: ((inputs.runner || 'ubuntu-24.04') != 'ubuntu-24.04') run: |- kubectl get svc -A diff --git a/.github/workflows/images-wo-checkout.yaml b/.github/workflows/images-wo-checkout.yaml index 8235426..6e8ed9c 100644 --- a/.github/workflows/images-wo-checkout.yaml +++ b/.github/workflows/images-wo-checkout.yaml @@ -18,10 +18,10 @@ on: runner: description: 'Runner type' required: true - default: 'ubuntu-22.04' + default: 'ubuntu-24.04' type: choice options: - - ubuntu-22.04 + - ubuntu-24.04 - matihost # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token permissions: @@ -34,8 +34,8 @@ env: IMAGE_TAG: "${{ github.ref == 'refs/heads/main' && 'latest' || github.sha }}" jobs: image-build-on-gcp-artifact-registry: - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} - if: ${{ (inputs.runner || 'ubuntu-22.04') != 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + if: ${{ (inputs.runner || 'ubuntu-24.04') != 'ubuntu-24.04' }} container: image: gcr.io/kaniko-project/executor:debug steps: @@ -55,8 +55,8 @@ jobs: --push-retry 2 --image-name-with-digest-file /workspace/image-digest.txt image-build-generic-registry: - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} - if: ${{ (inputs.runner || 'ubuntu-22.04') == 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + if: ${{ (inputs.runner || 'ubuntu-24.04') == 'ubuntu-24.04' }} container: image: gcr.io/kaniko-project/executor:debug steps: @@ -81,8 +81,8 @@ jobs: # kaniko does not allow to build second image - hence it has to run as separated job # https://github.com/GoogleContainerTools/kaniko/issues/1118 image-build-ghcr: - runs-on: ${{ inputs.runner || 'ubuntu-22.04' }} - if: ${{ (inputs.runner || 'ubuntu-22.04') == 'ubuntu-22.04' }} + runs-on: ${{ inputs.runner || 'ubuntu-24.04' }} + if: ${{ (inputs.runner || 'ubuntu-24.04') == 'ubuntu-24.04' }} container: image: gcr.io/kaniko-project/executor:debug steps: diff --git a/.github/workflows/kaniko.yaml b/.github/workflows/kaniko.yaml index 39691cb..8b8aad2 100644 --- a/.github/workflows/kaniko.yaml +++ b/.github/workflows/kaniko.yaml @@ -16,10 +16,10 @@ on: runner: description: 'Runner type' required: true - default: 'ubuntu-22.04' + default: 'ubuntu-24.04' type: choice options: - - ubuntu-22.04 + - ubuntu-24.04 - matihost # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token permissions: @@ -33,7 +33,7 @@ env: ROOT_IMAGE_TAG: "${{ github.ref == 'refs/heads/main' && 'root' || format('root-{0}', github.sha) }}" jobs: images: - runs-on: 'ubuntu-22.04' + runs-on: 'ubuntu-24.04' container: image: maven:3-eclipse-temurin-21 steps: diff --git a/.github/workflows/travis-ci.yaml b/.github/workflows/travis-ci.yaml index b91e510..2fd4cb4 100644 --- a/.github/workflows/travis-ci.yaml +++ b/.github/workflows/travis-ci.yaml @@ -26,7 +26,7 @@ permissions: contents: read jobs: java: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CACHE: java steps: @@ -43,7 +43,7 @@ jobs: java-version: '21' - run: cd java && make build project-euler: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CACHE: algorithms/project-euler steps: @@ -60,7 +60,7 @@ jobs: java-version: '21' - run: cd algorithms/project-euler && make build rust: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 @@ -74,7 +74,7 @@ jobs: key: "${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}" - run: cd rust/guessing_game && cargo build --verbose && cargo test --verbose go: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 @@ -90,7 +90,7 @@ jobs: go-version: '1.21' - run: cd go/learning && go get -d ./... && go build -mod=mod -o . ./... && go test ./pkg/language && ./language python: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 diff --git a/k8s/images/gh-images/Dockerfile b/k8s/images/gh-images/Dockerfile deleted file mode 100644 index cc6af56..0000000 --- a/k8s/images/gh-images/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -ARG JAVA_VERSION=21 -FROM alpine as certs -RUN apk --update add ca-certificates -FROM gcr.io/kaniko-project/executor:debug as kaniko -FROM maven:3-amazoncorretto-$JAVA_VERSION-debian -RUN apt -y update && apt -y install binutils curl wget lsb-release gnupg apt-transport-https ca-certificates \ - && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \ - && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list \ - && wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor > /usr/share/keyrings/hashicorp-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" > /etc/apt/sources.list.d/hashicorp.list \ - && apt -y update && apt -y install terraform google-cloud-cli kubectl google-cloud-cli-kubectl-oidc google-cloud-cli-gke-gcloud-auth-plugin \ - && rm -rf /var/lib/apt/lists/* -COPY --from=kaniko /kaniko /kaniko -COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -ENV PATH="/kaniko:${PATH}" -ENV DOCKER_CONFIG=/kaniko/.docker/ -ENV DOCKER_CREDENTIAL_GCR_CONFIG=/kaniko/.config/gcloud/docker_credential_gcr_config.json diff --git a/k8s/images/gh-images/cd/Dockerfile b/k8s/images/gh-images/cd/Dockerfile new file mode 100644 index 0000000..0e1055e --- /dev/null +++ b/k8s/images/gh-images/cd/Dockerfile @@ -0,0 +1,11 @@ +# syntax=docker/dockerfile:1 +FROM ubuntu:24.04 +RUN apt -y update && apt -y install binutils curl wget lsb-release gnupg apt-transport-https ca-certificates jq \ + && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - \ + && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list \ + && apt -y update && apt -y install google-cloud-cli kubectl google-cloud-cli-kubectl-oidc google-cloud-cli-gke-gcloud-auth-plugin +RUN curl -sL https://api.github.com/repos/opentofu/opentofu/releases/latest | jq -r ".assets[] | select(.name | test(\"amd64.deb\")) | .browser_download_url" | xargs curl -s -L -o "/tmp/tofu.deb" \ + && apt -y install /tmp/tofu.deb && rm -rf /tmp/tofu.deb \ + && curl -sL https://api.github.com/repos/gruntwork-io/terragrunt/releases/latest | jq -r ".assets[] | select(.name | test(\"linux_amd64\")) | .browser_download_url" | xargs curl -s -L -o "/usr/local/bin/terragrunt" \ + && chmod a+x /usr/local/bin/terragrunt \ + && rm -rf /var/lib/apt/lists/* diff --git a/k8s/images/gh-images/cd/Makefile b/k8s/images/gh-images/cd/Makefile new file mode 100644 index 0000000..e67b967 --- /dev/null +++ b/k8s/images/gh-images/cd/Makefile @@ -0,0 +1,29 @@ +TAG := latest +CURRENT_DIR := $(notdir $(shell pwd)) +NAME := $(CURRENT_DIR) +REPO := quay.io/matihost + +.EXPORT_ALL_VARIABLES: +BUILDKIT_PROGRESS=plain + +build: ## builds docker image + docker build --load -t $(REPO)/$(NAME):$(TAG) . + +push: ## push image with tag to quay.io repository (assume docker login quay.io has been perfomed) + docker push $(REPO)/$(NAME):$(TAG) + +tag: ## tag latest image with additional tag +ifeq ($(TAG),latest) + $(error TAG cannot be latest) +endif + docker tag $(REPO)/$(NAME):latest $(REPO)/$(NAME):$(TAG) + +run-bash: ## run image with bash + docker run -it --rm --entrypoint sh $(REPO)/$(NAME):${TAG} + + +help: ## show usage and tasks (default) + @eval $$(sed -E -n 's/^([\*\.a-zA-Z0-9_-]+):.*?## (.*)$$/printf "\\033[36m%-30s\\033[0m %s\\n" "\1" "\2" ;/; ta; b; :a p' $(MAKEFILE_LIST)) + +.DEFAULT_GOAL := help +.PHONY: help build diff --git a/k8s/images/gh-images/java-ci/Dockerfile b/k8s/images/gh-images/java-ci/Dockerfile new file mode 100644 index 0000000..60b3f7b --- /dev/null +++ b/k8s/images/gh-images/java-ci/Dockerfile @@ -0,0 +1,14 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv +ARG JAVA_VERSION=21 +FROM alpine AS certs +RUN apk --update add ca-certificates +FROM gcr.io/kaniko-project/executor:debug AS kaniko +FROM maven:3-eclipse-temurin-$JAVA_VERSION +RUN apt -y update && apt -y install binutils curl wget lsb-release gnupg apt-transport-https ca-certificates jq \ + && apt clean && apt autoclean && rm -rf /var/lib/apt/lists/* +COPY --from=kaniko /kaniko /kaniko +COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +ENV PATH="/kaniko:${PATH}" +ENV DOCKER_CONFIG=/kaniko/.docker/ +ENV DOCKER_CREDENTIAL_GCR_CONFIG=/kaniko/.config/gcloud/docker_credential_gcr_config.json diff --git a/k8s/images/gh-images/Makefile b/k8s/images/gh-images/java-ci/Makefile similarity index 58% rename from k8s/images/gh-images/Makefile rename to k8s/images/gh-images/java-ci/Makefile index c0206d9..d53a341 100644 --- a/k8s/images/gh-images/Makefile +++ b/k8s/images/gh-images/java-ci/Makefile @@ -1,19 +1,26 @@ TAG := latest JAVA_VERSION := 21 +CURRENT_DIR := $(notdir $(shell pwd)) +NAME := $(CURRENT_DIR) +REPO := quay.io/matihost + +.EXPORT_ALL_VARIABLES: +BUILDKIT_PROGRESS=plain + build: ## builds docker image - DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=plain docker build --build-arg=JAVA_VERSION=$(JAVA_VERSION) -t quay.io/matihost/gh-gcp-java-kaniko:$(TAG) . + docker build --load --build-arg=JAVA_VERSION=$(JAVA_VERSION) -t $(REPO)/$(NAME):$(TAG) . push: ## push image with tag to quay.io repository (assume docker login quay.io has been perfomed) - docker push quay.io/matihost/gh-gcp-java-kaniko:$(TAG) + docker push $(REPO)/$(NAME):$(TAG) tag: ## tag latest image with additional tag ifeq ($(TAG),latest) $(error TAG cannot be latest) endif - docker tag quay.io/matihost/gh-gcp-java-kaniko:latest quay.io/matihost/gh-gcp-java-kaniko:$(TAG) + docker tag $(REPO)/$(NAME):latest $(REPO)/$(NAME):$(TAG) run-bash: ## run image with bash - docker run -it --rm --entrypoint sh quay.io/matihost/gh-gcp-java-kaniko:${TAG} + docker run -it --rm --entrypoint sh $(REPO)/$(NAME):${TAG} help: ## show usage and tasks (default) diff --git a/terraform/aws/aws-github-oidc/Makefile b/terraform/aws/aws-github-oidc/Makefile new file mode 100644 index 0000000..4fc191d --- /dev/null +++ b/terraform/aws/aws-github-oidc/Makefile @@ -0,0 +1,39 @@ +.EXPORT_ALL_VARIABLES: + +DEBUG := false +ifeq ($(strip $(DEBUG)),true) + TF_LOG := DEBUG + TG_FLAGS := --terragrunt-debug +endif + +MODE := apply +ifeq ($(strip $(MODE)),apply) + MODE_STR := apply -auto-approve +else ifeq ($(strip $(MODE)),destroy) + MODE_STR := destroy -auto-approve +else + MODE_STR := plan +endif + + +ENV := current + +init: + cd stage/$(ENV) && terragrunt init -upgrade=true + + +run: init ## setup VPC: make run [ENV=dev] [MODE=apply] + @cd stage/$(ENV) && terragrunt validate && terragrunt $(MODE_STR) --terragrunt-non-interactive $(TG_FLAGS) + + +show-state: ## show state + cd stage/current && terragrunt state list && terragrunt show + +clean: ## clean cached plugins and data + find . -name ".terra*" -exec rm -rf {} + + find . -name "target" -exec rm -rf {} + + +help: ## show usage and tasks (default) + @eval $$(sed -E -n 's/^([\*\.a-zA-Z0-9_-]+):.*?## (.*)$$/printf "\\033[36m%-30s\\033[0m %s\\n" "\1" "\2" ;/; ta; b; :a p' $(MAKEFILE_LIST)) +.DEFAULT_GOAL := help +.PHONY: help apply destro diff --git a/terraform/aws/aws-github-oidc/README.md b/terraform/aws/aws-github-oidc/README.md new file mode 100644 index 0000000..6a675a9 --- /dev/null +++ b/terraform/aws/aws-github-oidc/README.md @@ -0,0 +1,32 @@ +# Terraform :: AWS GitHub OIDC provider + +Terraform scripts creating: + +- OIDC provider allowing github assume role on behalf of GitHub Actions invocation + +- OIDC role which can be assumed by GitHub action for selected GitHub repositories + +This setup use AWS resources eliglible to AWS Free Tier __only__. + +## Prerequisites + +- Logged to AWS Account + +```bash +aws configure +``` + +- Latest Terraform installed + +## Usage + +```bash +# setup OIDC provider and role +make run ENV=dev MODE=apply + +# show Terraform state +make show-state + +# terminates all AWS resource created with apply task +make destroy +``` diff --git a/terraform/aws/aws-github-oidc/module/oidc.tf b/terraform/aws/aws-github-oidc/module/oidc.tf new file mode 100644 index 0000000..9835140 --- /dev/null +++ b/terraform/aws/aws-github-oidc/module/oidc.tf @@ -0,0 +1,50 @@ +resource "aws_iam_openid_connect_provider" "github_actions" { + url = "https://token.actions.githubusercontent.com" + client_id_list = ["sts.amazonaws.com"] + + # Note that the thumbprint below has been set to all F's + # because the thumbprint is not used when authenticating token.actions.githubusercontent.com. + # This is a special case used only when GitHub's OIDC is authenticating to IAM. + # IAM uses its library of trusted CAs to authenticate. The value is still the API, so it must be specified. + thumbprint_list = ["ffffffffffffffffffffffffffffffffffffffff"] +} + + +resource "aws_iam_role" "oidc_role" { + name = var.oidc_role_name + description = "Role assumed by the GitHub OIDC provider." + max_session_duration = 3600 + assume_role_policy = data.aws_iam_policy_document.oidc_assume_policy.json + + depends_on = [aws_iam_openid_connect_provider.github_actions] +} + + +resource "aws_iam_role_policy_attachment" "oidc_role_policy_attachment" { + for_each = var.oidc_role_policies + + policy_arn = each.key + role = aws_iam_role.oidc_role.name +} + +data "aws_iam_policy_document" "oidc_assume_policy" { + + statement { + actions = ["sts:AssumeRoleWithWebIdentity"] + effect = "Allow" + + condition { + test = "StringLike" + values = [ + for repo in var.oidc_github_repositories : + "repo:%{if length(regexall(":+", repo)) > 0}${repo}%{else}${repo}:*%{endif}" + ] + variable = "token.actions.githubusercontent.com:sub" + } + + principals { + identifiers = [aws_iam_openid_connect_provider.github_actions.arn] + type = "Federated" + } + } +} diff --git a/terraform/aws/aws-github-oidc/module/variables.tf b/terraform/aws/aws-github-oidc/module/variables.tf new file mode 100644 index 0000000..d11c39a --- /dev/null +++ b/terraform/aws/aws-github-oidc/module/variables.tf @@ -0,0 +1,44 @@ +# tflint-ignore: terraform_unused_declarations +variable "zone" { + default = "us-east-1a" + type = string + description = "Preffered AWS AZ where resources need to placed, has to be compatible with region variable" +} + +# tflint-ignore: terraform_unused_declarations +variable "region" { + default = "us-east-1" + type = string + description = "Preffered AWS region where resource need to be placed" +} + + +variable "oidc_github_repositories" { + description = "List of GitHub organization/repository names authorized to assume the role." + type = list(string) + default = [] + + validation { + # Ensures each element of github_repositories list matches the + # organization/repository format used by GitHub. + condition = length([ + for repo in var.oidc_github_repositories : 1 + if length(regexall("^[A-Za-z0-9_.-]+?/([A-Za-z0-9_.:/-]+|\\*)$", repo)) > 0 + ]) == length(var.oidc_github_repositories) + error_message = "Repositories must be specified in the organization/repository format." + } +} + + +variable "oidc_role_name" { + default = "github-oidc" + type = string + description = "OIDC role name to be assumed" +} + + +variable "oidc_role_policies" { + description = "Policies to attach to OIDC role." + type = set(string) + default = [] +} diff --git a/terraform/aws/aws-github-oidc/module/versions.tf b/terraform/aws/aws-github-oidc/module/versions.tf new file mode 100644 index 0000000..9d04948 --- /dev/null +++ b/terraform/aws/aws-github-oidc/module/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5" + } + random = { + source = "hashicorp/random" + } + } + required_version = ">= 1.0" +} diff --git a/terraform/aws/aws-github-oidc/stage/current/terragrunt.hcl b/terraform/aws/aws-github-oidc/stage/current/terragrunt.hcl new file mode 100644 index 0000000..8aafc6b --- /dev/null +++ b/terraform/aws/aws-github-oidc/stage/current/terragrunt.hcl @@ -0,0 +1,23 @@ +include { + path = find_in_parent_folders() +} + +terraform { + # https://github.com/gruntwork-io/terragrunt/issues/1675 + source = "${find_in_parent_folders("module")}///" +} + + +inputs = { + oidc_github_repositories = [ + "matihost/monorepo" + ] + + oidc_role_name = "github-oidc" + oidc_role_policies = [ + "arn:aws:iam::aws:policy/AmazonS3FullAccess", + "arn:aws:iam::aws:policy/CloudFrontFullAccess", + ] + + +} diff --git a/terraform/aws/aws-github-oidc/stage/terragrunt.hcl b/terraform/aws/aws-github-oidc/stage/terragrunt.hcl new file mode 100644 index 0000000..322c9e1 --- /dev/null +++ b/terraform/aws/aws-github-oidc/stage/terragrunt.hcl @@ -0,0 +1,49 @@ +locals { + bucket = "${local.account}-terraform-state" + account = "${run_cmd("--terragrunt-quiet", "aws", "sts", "get-caller-identity", "--query", "\"Account\"", "--output", "text")}" + region = "${get_env("AWS_REGION", "us-east-1")}" + zone = "us-east-1a" +} + +remote_state { + backend = "s3" + generate = { + path = "state.tf" + if_exists = "overwrite_terragrunt" + } + config = { + bucket = local.bucket + key = "${basename(abspath("${get_parent_terragrunt_dir()}/.."))}/${basename(get_parent_terragrunt_dir())}/${path_relative_to_include()}/terraform.tfstate" + region = local.region + # TODO play with it... maybe not in free tier + # encrypt = true + # dynamodb_table = "my-lock-table" + } +} + + +generate "provider" { + path = "provider.tf" + if_exists = "overwrite_terragrunt" + contents = <