diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 41c310fa..8c60230f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,28 +3,28 @@ # These owners will be the default owners for everything in the # repo. Unless a later match takes precedence, these owners will be # requested for review when someone opens a pull request. -* @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +* @dav3r @felddy @jsf9k @mcdonnnj # These folks own any files in the .github directory at the root of # the repository and any of its subdirectories. -/.github/ @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.github/ @dav3r @felddy @jsf9k @mcdonnnj # Let jsf9k own the sometimes-touchy AWS and Python playbooks, as well -# as the packer.pkr.hcl file. -/src/aws.yml @jsf9k -/src/packer.pkr.hcl @jsf9k -/src/python.yml @jsf9k +# as the Packer template. +/*.pkr.hcl @jsf9k +/ansible/aws.yml @jsf9k +/ansible/python.yml @jsf9k # These folks own all linting configuration files. -/.ansible-lint @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.bandit.yml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.flake8 @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.isort.cfg @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.mdl_config.yaml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.pre-commit-config.yaml @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.prettierignore @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/.yamllint @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/requirements.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/requirements-dev.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/requirements-test.txt @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj -/setup-env @dav3r @felddy @jasonodoom @jsf9k @mcdonnnj +/.ansible-lint @dav3r @felddy @jsf9k @mcdonnnj +/.bandit.yml @dav3r @felddy @jsf9k @mcdonnnj +/.flake8 @dav3r @felddy @jsf9k @mcdonnnj +/.isort.cfg @dav3r @felddy @jsf9k @mcdonnnj +/.mdl_config.yaml @dav3r @felddy @jsf9k @mcdonnnj +/.pre-commit-config.yaml @dav3r @felddy @jsf9k @mcdonnnj +/.prettierignore @dav3r @felddy @jsf9k @mcdonnnj +/.yamllint @dav3r @felddy @jsf9k @mcdonnnj +/requirements.txt @dav3r @felddy @jsf9k @mcdonnnj +/requirements-dev.txt @dav3r @felddy @jsf9k @mcdonnnj +/requirements-test.txt @dav3r @felddy @jsf9k @mcdonnnj +/setup-env @dav3r @felddy @jsf9k @mcdonnnj diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e316b0d1..c0add003 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,9 +13,12 @@ updates: - dependency-name: actions/checkout - dependency-name: actions/setup-go - dependency-name: actions/setup-python + - dependency-name: cisagov/setup-env-github-action - dependency-name: crazy-max/ghaction-dump-context - dependency-name: crazy-max/ghaction-github-labeler - dependency-name: crazy-max/ghaction-github-status + - dependency-name: GitHubSecurityLab/actions-permissions + - dependency-name: hashicorp/setup-packer - dependency-name: hashicorp/setup-terraform - dependency-name: mxschmitt/action-tmate - dependency-name: step-security/harden-runner diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3928aa66..59e1e34e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,6 @@ defaults: env: AWS_DEFAULT_REGION: us-east-1 - CURL_CACHE_DIR: ~/.cache/curl PIP_CACHE_DIR: ~/.cache/pip PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit RUN_TMATE: ${{ secrets.RUN_TMATE }} @@ -32,10 +31,18 @@ env: jobs: diagnostics: name: Run diagnostics + # This job does not need any permissions + permissions: {} runs-on: ubuntu-latest steps: # Note that a duplicate of this step must be added at the top of # each job. + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} + # Note that a duplicate of this step must be added at the top of + # each job. - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -50,8 +57,15 @@ jobs: lint: needs: - diagnostics + permissions: + # actions/checkout needs this to fetch code + contents: read runs-on: ubuntu-latest steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -77,7 +91,7 @@ jobs: name: Lookup Go cache directory run: | echo "dir=$(go env GOCACHE)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ py${{ steps.setup-python.outputs.python-version }}-\ @@ -98,25 +112,12 @@ jobs: path: | ${{ env.PIP_CACHE_DIR }} ${{ env.PRE_COMMIT_CACHE_DIR }} - ${{ env.CURL_CACHE_DIR }} ${{ steps.go-cache.outputs.dir }} restore-keys: | ${{ env.BASE_CACHE_KEY }} - - name: Setup curl cache - run: mkdir -p ${{ env.CURL_CACHE_DIR }} - - name: Install Packer - env: - PACKER_VERSION: ${{ steps.setup-env.outputs.packer-version }} - run: | - PACKER_ZIP="packer_${PACKER_VERSION}_linux_amd64.zip" - curl --output ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --time-cond ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --location \ - "https://releases.hashicorp.com/packer/${PACKER_VERSION}/${PACKER_ZIP}" - sudo unzip -d /opt/packer \ - ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" - sudo mv /usr/local/bin/packer /usr/local/bin/packer-default - sudo ln -s /opt/packer/packer /usr/local/bin/packer + - uses: hashicorp/setup-packer@v3 + with: + version: ${{ steps.setup-env.outputs.packer-version }} - uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ steps.setup-env.outputs.terraform-version }} @@ -162,11 +163,11 @@ jobs: python -m pip install --upgrade pip setuptools wheel pip install --upgrade --requirement requirements-test.txt - name: Install Ansible roles - run: ansible-galaxy install --force --role-file src/requirements.yml + run: ansible-galaxy install --force --role-file ansible/requirements.yml # This must happen before pre-commit is run or the Packer format # linter will throw an error. - name: Install Packer plugins - run: packer init src + run: packer init . - name: Set up pre-commit hook environments run: pre-commit install-hooks - name: Run pre-commit on all files @@ -177,8 +178,15 @@ jobs: test: needs: - diagnostics + permissions: + # actions/checkout needs this to fetch code + contents: read runs-on: ubuntu-latest steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -191,7 +199,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ steps.setup-env.outputs.python-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ py${{ steps.setup-python.outputs.python-version }}-\ @@ -199,27 +207,14 @@ jobs: with: path: | ${{ env.PIP_CACHE_DIR }} - ${{ env.CURL_CACHE_DIR }} key: "${{ env.BASE_CACHE_KEY }}\ ${{ hashFiles('**/requirements-test.txt') }}-\ ${{ hashFiles('**/requirements.txt') }}" restore-keys: | ${{ env.BASE_CACHE_KEY }} - - name: Setup curl cache - run: mkdir -p ${{ env.CURL_CACHE_DIR }} - - name: Install Packer - env: - PACKER_VERSION: ${{ steps.setup-env.outputs.packer-version }} - run: | - PACKER_ZIP="packer_${PACKER_VERSION}_linux_amd64.zip" - curl --output ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --time-cond ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --location \ - "https://releases.hashicorp.com/packer/${PACKER_VERSION}/${PACKER_ZIP}" - sudo unzip -d /opt/packer \ - ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" - sudo mv /usr/local/bin/packer /usr/local/bin/packer-default - sudo ln -s /opt/packer/packer /usr/local/bin/packer + - uses: hashicorp/setup-packer@v3 + with: + version: ${{ steps.setup-env.outputs.packer-version }} - name: Install dependencies run: | python -m pip install --upgrade pip @@ -237,6 +232,9 @@ jobs: needs: - lint - test + permissions: + # actions/checkout needs this to fetch code + contents: read runs-on: ubuntu-latest strategy: fail-fast: false @@ -245,6 +243,10 @@ jobs: - arm64 - x86_64 steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -257,7 +259,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ steps.setup-env.outputs.python-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ py${{ steps.setup-python.outputs.python-version }}-\ @@ -266,26 +268,13 @@ jobs: with: path: | ${{ env.PIP_CACHE_DIR }} - ${{ env.CURL_CACHE_DIR }} key: "${{ env.BASE_CACHE_KEY }}\ ${{ hashFiles('**/requirements.txt') }}" restore-keys: | ${{ env.BASE_CACHE_KEY }} - - name: Setup curl cache - run: mkdir -p ${{ env.CURL_CACHE_DIR }} - - name: Install Packer - env: - PACKER_VERSION: ${{ steps.setup-env.outputs.packer-version }} - run: | - PACKER_ZIP="packer_${PACKER_VERSION}_linux_amd64.zip" - curl --output ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --time-cond ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --location \ - "https://releases.hashicorp.com/packer/${PACKER_VERSION}/${PACKER_ZIP}" - sudo unzip -d /opt/packer \ - ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" - sudo mv /usr/local/bin/packer /usr/local/bin/packer-default - sudo ln -s /opt/packer/packer /usr/local/bin/packer + - uses: hashicorp/setup-packer@v3 + with: + version: ${{ steps.setup-env.outputs.packer-version }} - uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ steps.setup-env.outputs.terraform-version }} @@ -295,7 +284,7 @@ jobs: pip install --upgrade \ --requirement requirements.txt - name: Install Ansible roles - run: ansible-galaxy install --force --role-file src/requirements.yml + run: ansible-galaxy install --force --role-file ansible/requirements.yml - name: Assume AWS build role uses: aws-actions/configure-aws-credentials@v4 with: @@ -316,7 +305,7 @@ jobs: sudo ln -s ${{ env.pythonLocation }}/bin/python3 \ /usr/bin/python3 - name: Install Packer plugins - run: packer init src + run: packer init . - name: Create machine image # This runs through the AMI creation process but does not # actually create an AMI @@ -324,7 +313,7 @@ jobs: packer build -only amazon-ebs.${{ matrix.architecture }} \ -timestamp-ui \ -var skip_create_ami=true \ - src/packer.pkr.hcl + . - name: Remove /usr/bin/python3 symlink to the installed Python run: | sudo mv /usr/bin/python3-default /usr/bin/python3 diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index dcc3d6a0..e75bb2fc 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -7,17 +7,24 @@ on: env: AWS_DEFAULT_REGION: us-east-1 - CURL_CACHE_DIR: ~/.cache/curl PIP_CACHE_DIR: ~/.cache/pip RUN_TMATE: ${{ secrets.RUN_TMATE }} jobs: diagnostics: name: Run diagnostics + # This job does not need any permissions + permissions: {} runs-on: ubuntu-latest steps: # Note that a duplicate of this step must be added at the top of # each job. + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} + # Note that a duplicate of this step must be added at the top of + # each job. - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -32,6 +39,9 @@ jobs: prerelease: needs: - diagnostics + permissions: + # actions/checkout needs this to fetch code + contents: read runs-on: ubuntu-latest strategy: fail-fast: false @@ -40,6 +50,10 @@ jobs: - arm64 - x86_64 steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -52,7 +66,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ steps.setup-env.outputs.python-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ py${{ steps.setup-python.outputs.python-version }}-\ @@ -61,26 +75,13 @@ jobs: with: path: | ${{ env.PIP_CACHE_DIR }} - ${{ env.CURL_CACHE_DIR }} key: "${{ env.BASE_CACHE_KEY }}\ ${{ hashFiles('**/requirements.txt') }}" restore-keys: | ${{ env.BASE_CACHE_KEY }} - - name: Setup curl cache - run: mkdir -p ${{ env.CURL_CACHE_DIR }} - - name: Install Packer - env: - PACKER_VERSION: ${{ steps.setup-env.outputs.packer-version }} - run: | - PACKER_ZIP="packer_${PACKER_VERSION}_linux_amd64.zip" - curl --output ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --time-cond ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --location \ - "https://releases.hashicorp.com/packer/${PACKER_VERSION}/${PACKER_ZIP}" - sudo unzip -d /opt/packer \ - ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" - sudo mv /usr/local/bin/packer /usr/local/bin/packer-default - sudo ln -s /opt/packer/packer /usr/local/bin/packer + - uses: hashicorp/setup-packer@v3 + with: + version: ${{ steps.setup-env.outputs.packer-version }} - uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ steps.setup-env.outputs.terraform-version }} @@ -90,7 +91,7 @@ jobs: pip install --upgrade \ --requirement requirements.txt - name: Install ansible roles - run: ansible-galaxy install --force --role-file src/requirements.yml + run: ansible-galaxy install --force --role-file ansible/requirements.yml - name: Assume AWS build role uses: aws-actions/configure-aws-credentials@v4 with: @@ -111,7 +112,7 @@ jobs: sudo ln -s ${{ env.pythonLocation }}/bin/python3 \ /usr/bin/python3 - name: Install Packer plugins - run: packer init src + run: packer init . - name: Create machine image run: | packer build -only amazon-ebs.${{ matrix.architecture }} \ @@ -119,7 +120,7 @@ jobs: -var is_prerelease=${{ github.event.release.prerelease }} \ -var release_tag=${{ github.event.release.tag_name }} \ -var release_url=${{ github.event.release.html_url }} \ - src/packer.pkr.hcl + . - name: Remove /usr/bin/python3 symlink to the installed python run: | sudo mv /usr/bin/python3-default /usr/bin/python3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f0555082..3b7e98f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,17 +14,24 @@ env: # COPY_REGIONS_KMS_MAP: "us-east-2:alias/cool-amis, # us-west-1:alias/cool-amis, # us-west-2:alias/cool-amis" - CURL_CACHE_DIR: ~/.cache/curl PIP_CACHE_DIR: ~/.cache/pip RUN_TMATE: ${{ secrets.RUN_TMATE }} jobs: diagnostics: name: Run diagnostics + # This job does not need any permissions + permissions: {} runs-on: ubuntu-latest steps: # Note that a duplicate of this step must be added at the top of # each job. + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} + # Note that a duplicate of this step must be added at the top of + # each job. - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -39,6 +46,9 @@ jobs: release: needs: - diagnostics + permissions: + # actions/checkout needs this to fetch code + contents: read runs-on: ubuntu-latest strategy: fail-fast: false @@ -47,6 +57,10 @@ jobs: - arm64 - x86_64 steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -59,7 +73,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ steps.setup-env.outputs.python-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 env: BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\ py${{ steps.setup-python.outputs.python-version }}-\ @@ -68,26 +82,13 @@ jobs: with: path: | ${{ env.PIP_CACHE_DIR }} - ${{ env.CURL_CACHE_DIR }} key: "${{ env.BASE_CACHE_KEY }}\ ${{ hashFiles('**/requirements.txt') }}" restore-keys: | ${{ env.BASE_CACHE_KEY }} - - name: Setup curl cache - run: mkdir -p ${{ env.CURL_CACHE_DIR }} - - name: Install Packer - env: - PACKER_VERSION: ${{ steps.setup-env.outputs.packer-version }} - run: | - PACKER_ZIP="packer_${PACKER_VERSION}_linux_amd64.zip" - curl --output ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --time-cond ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" \ - --location \ - "https://releases.hashicorp.com/packer/${PACKER_VERSION}/${PACKER_ZIP}" - sudo unzip -d /opt/packer \ - ${{ env.CURL_CACHE_DIR }}/"${PACKER_ZIP}" - sudo mv /usr/local/bin/packer /usr/local/bin/packer-default - sudo ln -s /opt/packer/packer /usr/local/bin/packer + - uses: hashicorp/setup-packer@v3 + with: + version: ${{ steps.setup-env.outputs.packer-version }} - uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ steps.setup-env.outputs.terraform-version }} @@ -97,7 +98,7 @@ jobs: pip install --upgrade \ --requirement requirements.txt - name: Install ansible roles - run: ansible-galaxy install --force --role-file src/requirements.yml + run: ansible-galaxy install --force --role-file ansible/requirements.yml # Do not copy the AMI to other regions until we have figured out a # workable mechanism for creating and managing AMI KMS keys in other # regions. @@ -105,7 +106,7 @@ jobs: # - name: Add copy regions to packer configuration # run: | # echo $COPY_REGIONS_KMS_MAP | \ - # ./patch_packer_config.py src/packer.pkr.hcl + # ./patch_packer_config.py variables.pkr.hcl - name: Assume AWS build role uses: aws-actions/configure-aws-credentials@v4 with: @@ -126,7 +127,7 @@ jobs: sudo ln -s ${{ env.pythonLocation }}/bin/python3 \ /usr/bin/python3 - name: Install Packer plugins - run: packer init src + run: packer init . - name: Create machine image run: | packer build -only amazon-ebs.${{ matrix.architecture }} \ @@ -134,7 +135,7 @@ jobs: -var is_prerelease=${{ github.event.release.prerelease }} \ -var release_tag=${{ github.event.release.tag_name }} \ -var release_url=${{ github.event.release.html_url }} \ - src/packer.pkr.hcl + . - name: Remove /usr/bin/python3 symlink to the installed python run: | sudo mv /usr/bin/python3-default /usr/bin/python3 diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 5a20438e..00051472 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -4,8 +4,9 @@ name: sync-labels on: push: paths: - - '.github/labels.yml' - - '.github/workflows/sync-labels.yml' + - .github/labels.yml + - .github/workflows/sync-labels.yml + workflow_dispatch: permissions: contents: read @@ -13,10 +14,18 @@ permissions: jobs: diagnostics: name: Run diagnostics + # This job does not need any permissions + permissions: {} runs-on: ubuntu-latest steps: # Note that a duplicate of this step must be added at the top of # each job. + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} + # Note that a duplicate of this step must be added at the top of + # each job. - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 @@ -24,7 +33,7 @@ jobs: egress-policy: audit - id: github-status name: Check GitHub status - uses: crazy-max/ghaction-github-status@v3 + uses: crazy-max/ghaction-github-status@v4 - id: dump-context name: Dump context uses: crazy-max/ghaction-dump-context@v2 @@ -38,6 +47,10 @@ jobs: issues: write runs-on: ubuntu-latest steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + # Uses the organization variable unless overridden + config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }} - id: harden-runner name: Harden the runner uses: step-security/harden-runner@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a5000f4..026f6b89 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,22 +4,30 @@ default_language_version: python: python3 repos: + # Check the pre-commit configuration + - repo: meta + hooks: + - id: check-useless-excludes + - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: check-case-conflict - id: check-executables-have-shebangs - id: check-json - id: check-merge-conflict + - id: check-shebang-scripts-are-executable + - id: check-symlinks - id: check-toml + - id: check-vcs-permalinks - id: check-xml - id: debug-statements + - id: destroyed-symlinks - id: detect-aws-credentials args: - --allow-missing-credentials - id: detect-private-key - id: end-of-file-fixer - exclude: files/(issue|motd) - id: mixed-line-ending args: - --fix=lf @@ -31,22 +39,15 @@ repos: # Text file hooks - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.41.0 + rev: v0.42.0 hooks: - id: markdownlint args: - --config=.mdl_config.yaml - - repo: https://github.com/pre-commit/mirrors-prettier - # This is the last version of v3 available from the mirror. We should hold - # here until v4, which is currently in alpha, is more stable. - rev: v3.1.0 + - repo: https://github.com/rbubley/mirrors-prettier + rev: v3.3.3 hooks: - id: prettier - # This is the latest version of v3 available from NPM. The pre-commit - # mirror does not pull tags for old major versions once a new major - # version tag is published. - additional_dependencies: - - prettier@3.3.1 - repo: https://github.com/adrienverge/yamllint rev: v1.35.1 hooks: @@ -56,14 +57,14 @@ repos: # GitHub Actions hooks - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.4 + rev: 0.29.4 hooks: - id: check-github-actions - id: check-github-workflows # pre-commit hooks - repo: https://github.com/pre-commit/pre-commit - rev: v3.7.1 + rev: v4.0.1 hooks: - id: validate_manifest @@ -71,25 +72,25 @@ repos: - repo: https://github.com/TekWizely/pre-commit-golang rev: v1.0.0-rc.1 hooks: - # Style Checkers - - id: go-critic - # StaticCheck - - id: go-staticcheck-repo-mod # Go Build - id: go-build-repo-mod + # Style Checkers + - id: go-critic + # goimports + - id: go-imports-repo + args: + # Write changes to files + - -w # Go Mod Tidy - id: go-mod-tidy-repo + # GoSec + - id: go-sec-repo-mod + # StaticCheck + - id: go-staticcheck-repo-mod # Go Test - id: go-test-repo-mod # Go Vet - id: go-vet-repo-mod - # GoSec - - id: go-sec-repo-mod - # goimports - - id: go-imports-repo - args: - # Write changes to files - - -w # Nix hooks - repo: https://github.com/nix-community/nixpkgs-fmt rev: v1.3.0 @@ -98,7 +99,7 @@ repos: # Shell script hooks - repo: https://github.com/scop/pre-commit-shfmt - rev: v3.8.0-1 + rev: v3.10.0-1 hooks: - id: shfmt args: @@ -123,7 +124,7 @@ repos: # Python hooks # Run bandit on the "tests" tree with a configuration - repo: https://github.com/PyCQA/bandit - rev: 1.7.8 + rev: 1.7.10 hooks: - id: bandit name: bandit (tests tree) @@ -132,37 +133,54 @@ repos: - --config=.bandit.yml # Run bandit on everything except the "tests" tree - repo: https://github.com/PyCQA/bandit - rev: 1.7.7 + rev: 1.7.10 hooks: - id: bandit name: bandit (everything else) exclude: tests - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.4.2 + rev: 24.10.0 hooks: - id: black - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 + rev: 7.1.1 hooks: - id: flake8 additional_dependencies: - - flake8-docstrings + - flake8-docstrings==1.7.0 - repo: https://github.com/PyCQA/isort rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 + rev: v1.13.0 hooks: - id: mypy + - repo: https://github.com/pypa/pip-audit + rev: v2.7.3 + hooks: + - id: pip-audit + args: + # We have to ignore this particular vulnerability in + # ansible-core>=2.11 as there is currently no fix. See + # cisagov/skeleton-packer#380 for more details. + - --ignore-vuln + - GHSA-99w6-3xph-cx78 + # Add any pip requirements files to scan + - --requirement + - requirements-dev.txt + - --requirement + - requirements-test.txt + - --requirement + - requirements.txt - repo: https://github.com/asottile/pyupgrade - rev: v3.15.2 + rev: v3.19.0 hooks: - id: pyupgrade # Ansible hooks - repo: https://github.com/ansible/ansible-lint - rev: v24.6.0 + rev: v24.10.0 hooks: - id: ansible-lint additional_dependencies: @@ -173,21 +191,40 @@ repos: # necessary to add the ansible package itself as an # additional dependency, with the same pinning as is done in # requirements-test.txt of cisagov/skeleton-ansible-role. - # - ansible>=9,<10 + # + # Version 10 is required because the pip-audit pre-commit + # hook identifies a vulnerability in ansible-core 2.16.13, + # but all versions of ansible 9 have a dependency on + # ~=2.16.X. + # + # It is also a good idea to go ahead and upgrade to version + # 10 since version 9 is going EOL at the end of November: + # https://endoflife.date/ansible + # - ansible>=10,<11 # ansible-core 2.16.3 through 2.16.6 suffer from the bug # discussed in ansible/ansible#82702, which breaks any # symlinked files in vars, tasks, etc. for any Ansible role # installed via ansible-galaxy. Hence we never want to # install those versions. # + # Note that the pip-audit pre-commit hook identifies a + # vulnerability in ansible-core 2.16.13. The pin of + # ansible-core to >=2.17 effectively also pins ansible to + # >=10. + # + # It is also a good idea to go ahead and upgrade to + # ansible-core 2.17 since security support for ansible-core + # 2.16 ends this month: + # https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix + # # Note that any changes made to this dependency must also be # made in requirements.txt in cisagov/skeleton-packer and # requirements-test.txt in cisagov/skeleton-ansible-role. - - ansible-core>=2.16.7 + - ansible-core>=2.17 # Terraform hooks - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.90.0 + rev: v1.96.1 hooks: - id: terraform_fmt - id: terraform_validate @@ -200,7 +237,7 @@ repos: # Packer hooks - repo: https://github.com/cisagov/pre-commit-packer - rev: v0.0.2 + rev: v0.3.0 hooks: - - id: packer_validate - id: packer_fmt + - id: packer_validate diff --git a/.terraform-docs.yml b/.terraform-docs.yml new file mode 100644 index 00000000..575b15db --- /dev/null +++ b/.terraform-docs.yml @@ -0,0 +1,14 @@ +--- +formatter: markdown table +output: + file: README.md + mode: inject + template: |- + + {{ .Content }} + +settings: + anchor: false + atx-closed: true + html: false + lockfile: false diff --git a/README.md b/README.md index 31003853..36f2a563 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is a generic skeleton project that can be used to quickly get a new [cisagov](https://github.com/cisagov) GitHub -[Packer](https://packer.io) project started. This skeleton project +[Packer](https://packer.io) template project started. This skeleton project contains [licensing information](LICENSE), as well as [pre-commit hooks](https://pre-commit.com) and [GitHub Actions](https://github.com/features/actions) configurations @@ -69,7 +69,7 @@ how the build was triggered from GitHub. 1. **Non-release test**: After a normal commit or pull request GitHub Actions will build the project, and run tests and validation on the - packer configuration. It will **not** build an image. + Packer template. It will **not** build an image. 1. **Pre-release deploy**: Publish a GitHub release with the "This is a pre-release" checkbox checked. An image will be built and deployed using the [`prerelease`](.github/workflows/prerelease.yml) @@ -104,20 +104,8 @@ source_profile = build-skeleton-packer role_session_name = example ``` -The [Packer template](src/packer.pkr.hcl) defines a number of variables: - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| ami\_regions | The list of AWS regions to copy the AMI to once it has been created. Example: ["us-east-1"] | `list(string)` | `[]` | no | -| build\_region | The region in which to retrieve the base AMI from and build the new AMI. | `string` | `"us-east-1"` | no | -| build\_region\_kms | The ID or ARN of the KMS key to use for AMI encryption. | `string` | `"alias/cool-amis"` | no | -| is\_prerelease | The pre-release status to use for the tags applied to the created AMI. | `bool` | `false` | no | -| region\_kms\_keys | A map of regions to copy the created AMI to and the KMS keys to use for encryption in that region. The keys for this map must match the values provided to the aws\_regions variable. Example: {"us-east-1": "alias/example-kms"} | `map(string)` | `{}` | no | -| release\_tag | The GitHub release tag to use for the tags applied to the created AMI. | `string` | `""` | no | -| release\_url | The GitHub release URL to use for the tags applied to the created AMI. | `string` | `""` | no | -| skip\_create\_ami | Indicate if Packer should not create the AMI. | `bool` | `false` | no | - -Changing these defaults can be done through a `.pkrvars.hcl` file: +This Packer template defines a number of variables whose defaults can be changed +through a `.pkrvars.hcl` file: ```hcl build_region = "us-east-2" @@ -129,12 +117,12 @@ Here is an example of how to kick off a pre-release build: ```console pip install --requirement requirements-dev.txt -ansible-galaxy install --force --force-with-deps --role-file src/requirements.yml -AWS_PROFILE=cool-images-ec2amicreate-skeleton-packer packer build --timestamp-ui -var release_tag=$(./bump_version.sh show) -var is_prerelease=true src/packer.pkr.hcl +ansible-galaxy install --force --force-with-deps --role-file ansible/requirements.yml +AWS_PROFILE=cool-images-ec2amicreate-skeleton-packer packer build --timestamp-ui -var release_tag=$(./bump_version.sh show) -var is_prerelease=true packer.pkr.hcl ``` If you are satisfied with your pre-release image, you can easily create a release -that deploys to all regions by adding additional regions to the packer configuration. +that deploys to all regions by adding additional regions to the Packer template. This can be done by using a `.pkrvars.hcl` for example with `release.pkrvars.hcl`: ```hcl @@ -147,7 +135,7 @@ region_kms_keys = { ``` ```console -AWS_PROFILE=cool-images-ec2amicreate-skeleton-packer packer build --timestamp-ui -var-file release.pkrvars.hcl src/packer.pkr.hcl +AWS_PROFILE=cool-images-ec2amicreate-skeleton-packer packer build --timestamp-ui -var-file release.pkrvars.hcl packer.pkr.hcl ``` ### Giving Other AWS Accounts Permission to Launch the Image ### @@ -166,6 +154,46 @@ terraform init --upgrade=true terraform apply ``` + +## Requirements ## + +No requirements. + +## Providers ## + +| Name | Version | +|------|---------| +| amazon-ami | n/a | + +## Modules ## + +No modules. + +## Resources ## + +| Name | Type | +|------|------| +| [amazon-ami_amazon-ami.debian_bookworm_arm64](https://registry.terraform.io/providers/hashicorp/amazon-ami/latest/docs/data-sources/amazon-ami) | data source | +| [amazon-ami_amazon-ami.debian_bookworm_x86_64](https://registry.terraform.io/providers/hashicorp/amazon-ami/latest/docs/data-sources/amazon-ami) | data source | + +## Inputs ## + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| ami\_regions | The list of AWS regions to copy the AMI to once it has been created. Example: ["us-east-1"] | `list(string)` | `[]` | no | +| build\_region | The region in which to retrieve the base AMI from and build the new AMI. | `string` | `"us-east-1"` | no | +| build\_region\_kms | The ID or ARN of the KMS key to use for AMI encryption. | `string` | `"alias/cool-amis"` | no | +| is\_prerelease | The pre-release status to use for the tags applied to the created AMI. | `bool` | `false` | no | +| region\_kms\_keys | A map of regions to copy the created AMI to and the KMS keys to use for encryption in that region. The keys for this map must match the values provided to the aws\_regions variable. Example: {"us-east-1": "alias/example-kms"} | `map(string)` | `{}` | no | +| release\_tag | The GitHub release tag to use for the tags applied to the created AMI. | `string` | `""` | no | +| release\_url | The GitHub release URL to use for the tags applied to the created AMI. | `string` | `""` | no | +| skip\_create\_ami | Indicate if Packer should not create the AMI. | `bool` | `false` | no | + +## Outputs ## + +No outputs. + + ## New Repositories from a Skeleton ## Please see our [Project Setup guide](https://github.com/cisagov/development-guide/tree/develop/project_setup) diff --git a/ami_arm64.pkr.hcl b/ami_arm64.pkr.hcl new file mode 100644 index 00000000..9e870641 --- /dev/null +++ b/ami_arm64.pkr.hcl @@ -0,0 +1,43 @@ +source "amazon-ebs" "arm64" { + ami_name = "example-hvm-${local.timestamp}-arm64-ebs" + ami_regions = var.ami_regions + associate_public_ip_address = true + encrypt_boot = true + instance_type = "t4g.small" + kms_key_id = var.build_region_kms + launch_block_device_mappings { + delete_on_termination = true + device_name = "/dev/xvda" + encrypted = true + volume_size = 8 + volume_type = "gp3" + } + region = var.build_region + region_kms_key_ids = var.region_kms_keys + skip_create_ami = var.skip_create_ami + source_ami = data.amazon-ami.debian_bookworm_arm64.id + ssh_username = "admin" + subnet_filter { + filters = { + "tag:Name" = "AMI Build" + } + } + tags = { + Application = "Example" + Architecture = "arm64" + Base_AMI_Name = data.amazon-ami.debian_bookworm_arm64.name + GitHub_Release_URL = var.release_url + OS_Version = "Debian Bookworm" + Pre_Release = var.is_prerelease + Release = var.release_tag + Team = "VM Fusion - Development" + } + # Many Linux distributions are now disallowing the use of RSA keys, + # so it makes sense to use an ED25519 key instead. + temporary_key_pair_type = "ed25519" + vpc_filter { + filters = { + "tag:Name" = "AMI Build" + } + } +} diff --git a/ami_x86_64.pkr.hcl b/ami_x86_64.pkr.hcl new file mode 100644 index 00000000..8976d2ac --- /dev/null +++ b/ami_x86_64.pkr.hcl @@ -0,0 +1,43 @@ +source "amazon-ebs" "x86_64" { + ami_name = "example-hvm-${local.timestamp}-x86_64-ebs" + ami_regions = var.ami_regions + associate_public_ip_address = true + encrypt_boot = true + instance_type = "t3.small" + kms_key_id = var.build_region_kms + launch_block_device_mappings { + delete_on_termination = true + device_name = "/dev/xvda" + encrypted = true + volume_size = 8 + volume_type = "gp3" + } + region = var.build_region + region_kms_key_ids = var.region_kms_keys + skip_create_ami = var.skip_create_ami + source_ami = data.amazon-ami.debian_bookworm_x86_64.id + ssh_username = "admin" + subnet_filter { + filters = { + "tag:Name" = "AMI Build" + } + } + tags = { + Application = "Example" + Architecture = "x86_64" + Base_AMI_Name = data.amazon-ami.debian_bookworm_x86_64.name + GitHub_Release_URL = var.release_url + OS_Version = "Debian Bookworm" + Pre_Release = var.is_prerelease + Release = var.release_tag + Team = "VM Fusion - Development" + } + # Many Linux distributions are now disallowing the use of RSA keys, + # so it makes sense to use an ED25519 key instead. + temporary_key_pair_type = "ed25519" + vpc_filter { + filters = { + "tag:Name" = "AMI Build" + } + } +} diff --git a/src/aws.yml b/ansible/aws.yml similarity index 100% rename from src/aws.yml rename to ansible/aws.yml diff --git a/src/base.yml b/ansible/base.yml similarity index 100% rename from src/base.yml rename to ansible/base.yml diff --git a/src/example.yml b/ansible/example.yml similarity index 100% rename from src/example.yml rename to ansible/example.yml diff --git a/src/install-prerequisites-for-netplan-configuration-fix.yml b/ansible/install-prerequisites-for-netplan-configuration-fix.yml similarity index 100% rename from src/install-prerequisites-for-netplan-configuration-fix.yml rename to ansible/install-prerequisites-for-netplan-configuration-fix.yml diff --git a/src/playbook.yml b/ansible/playbook.yml similarity index 100% rename from src/playbook.yml rename to ansible/playbook.yml diff --git a/src/python.yml b/ansible/python.yml similarity index 100% rename from src/python.yml rename to ansible/python.yml diff --git a/src/requirements.yml b/ansible/requirements.yml similarity index 100% rename from src/requirements.yml rename to ansible/requirements.yml diff --git a/src/upgrade.yml b/ansible/upgrade.yml similarity index 100% rename from src/upgrade.yml rename to ansible/upgrade.yml diff --git a/base_amis.pkr.hcl b/base_amis.pkr.hcl new file mode 100644 index 00000000..8f9f472c --- /dev/null +++ b/base_amis.pkr.hcl @@ -0,0 +1,23 @@ +data "amazon-ami" "debian_bookworm_arm64" { + filters = { + architecture = "arm64" + name = "debian-12-arm64-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["136693071363"] + region = var.build_region +} + +data "amazon-ami" "debian_bookworm_x86_64" { + filters = { + architecture = "x86_64" + name = "debian-12-amd64-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["136693071363"] + region = var.build_region +} diff --git a/build.pkr.hcl b/build.pkr.hcl new file mode 100644 index 00000000..b05ba95a --- /dev/null +++ b/build.pkr.hcl @@ -0,0 +1,31 @@ +build { + sources = [ + "source.amazon-ebs.arm64", + "source.amazon-ebs.x86_64", + ] + + provisioner "ansible" { + playbook_file = "ansible/upgrade.yml" + use_proxy = false + use_sftp = true + } + + provisioner "ansible" { + playbook_file = "ansible/python.yml" + use_proxy = false + use_sftp = true + } + + provisioner "ansible" { + ansible_env_vars = ["AWS_DEFAULT_REGION=${var.build_region}"] + playbook_file = "ansible/playbook.yml" + use_proxy = false + use_sftp = true + } + + provisioner "shell" { + execute_command = "chmod +x {{ .Path }}; sudo env {{ .Vars }} {{ .Path }} ; rm -f {{ .Path }}" + inline = ["sed -i '/^users:/ {N; s/users:.*/users: []/g}' /etc/cloud/cloud.cfg", "rm --force /etc/sudoers.d/90-cloud-init-users", "rm --force /root/.ssh/authorized_keys", "/usr/sbin/userdel --remove --force admin"] + skip_clean = true + } +} diff --git a/bump_version.sh b/bump_version.sh index 49e61365..1d8fc5d3 100755 --- a/bump_version.sh +++ b/bump_version.sh @@ -6,7 +6,7 @@ set -o nounset set -o errexit set -o pipefail -VERSION_FILE=src/version.txt +VERSION_FILE=version.txt HELP_INFORMATION="bump_version.sh (show|major|minor|patch|prerelease|build|finalize)" diff --git a/locals.pkr.hcl b/locals.pkr.hcl new file mode 100644 index 00000000..90911c57 --- /dev/null +++ b/locals.pkr.hcl @@ -0,0 +1,3 @@ +locals { + timestamp = regex_replace(timestamp(), "[- TZ:]", "") +} diff --git a/requirements.txt b/requirements.txt index bdf26b2a..5d2d6073 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,20 +8,37 @@ # as using the dnf package manager, and version 8 is currently the # oldest supported version. # -# We have tested against version 9. We want to avoid automatically +# Version 10 is required because the pip-audit pre-commit hook +# identifies a vulnerability in ansible-core 2.16.13, but all versions +# of ansible 9 have a dependency on ~=2.16.X. +# +# It is also a good idea to go ahead and upgrade to version 10 since +# version 9 is going EOL at the end of November: +# https://endoflife.date/ansible +# +# We have tested against version 10. We want to avoid automatically # jumping to another major version without testing, since there are # often breaking changes across major versions. This is the reason # for the upper bound. -ansible>=8,<10 +ansible>=10,<11 # ansible-core 2.16.3 through 2.16.6 suffer from the bug discussed in # ansible/ansible#82702, which breaks any symlinked files in vars, # tasks, etc. for any Ansible role installed via ansible-galaxy. # Hence we never want to install those versions. # +# Note that the pip-audit pre-commit hook identifies a vulnerability +# in ansible-core 2.16.13. Normally we would pin ansible-core +# accordingly (>2.16.13), but the above pin of ansible>=10 effectively +# pins ansible-core to >=2.17 anyway so that's what we use. +# +# It is also a good idea to go ahead and upgrade to ansible-core 2.17 +# since security support for ansible-core 2.16 ends this month: +# https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix +# # Note that any changes made to this dependency must also be made in # requirements-test.txt in cisagov/skeleton-ansible-role and # .pre-commit-config.yaml in cisagov/skeleton-generic. -ansible-core>=2.16.7 +ansible-core>=2.17 boto3 docopt semver diff --git a/setup-env b/setup-env index 7d42d25d..e1340b67 100755 --- a/setup-env +++ b/setup-env @@ -39,6 +39,52 @@ python_versions() { pyenv versions --bare --skip-aliases --skip-envs } +check_python_version() { + local version=$1 + + # This is a valid regex for semantically correct Python version strings. + # For more information see here: + # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + # Break down the regex into readable parts major.minor.patch + local major="0|[1-9]\d*" + local minor="0|[1-9]\d*" + local patch="0|[1-9]\d*" + + # Splitting the prerelease part for readability + # Start of the prerelease + local prerelease="(?:-" + # Numeric or alphanumeric identifiers + local prerelease+="(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)" + # Additional dot-separated identifiers + local prerelease+="(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*" + # End of the prerelease, making it optional + local prerelease+=")?" + # Optional build metadata + local build="(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?" + + # Final regex composed of parts + local regex="^($major)\.($minor)\.($patch)$prerelease$build$" + + # This checks if the Python version does not match the regex pattern specified in $regex, + # using Perl for regex matching. If the pattern is not found, then prompt the user with + # the invalid version message. + if ! echo "$version" | perl -ne "exit(!/$regex/)"; then + echo "Invalid version of Python: Python follows semantic versioning," \ + "so any version string that is not a valid semantic version is an" \ + "invalid version of Python." + exit 1 + # Else if the Python version isn't installed then notify the user. + # grep -E is used for searching through text lines that match the specific verison. + elif ! python_versions | grep -E "^${version}$" > /dev/null; then + echo "Error: Python version $version is not installed." + echo "Installed Python versions are:" + python_versions + exit 1 + else + echo "Using Python version $version" + fi +} + # Flag to force deletion and creation of virtual environment FORCE=0 @@ -144,17 +190,8 @@ while true; do -p | --python-version) PYTHON_VERSION="$2" shift 2 - # Check the Python versions being passed in. - if [ -n "${PYTHON_VERSION+x}" ]; then - if python_versions | grep -E "^${PYTHON_VERSION}$" > /dev/null; then - echo Using Python version "$PYTHON_VERSION" - else - echo Error: Python version "$PYTHON_VERSION" is not installed. - echo Installed Python versions are: - python_versions - exit 1 - fi - fi + # Check the Python version being passed in. + check_python_version "$PYTHON_VERSION" ;; -v | --venv-name) VENV_NAME="$2" @@ -188,15 +225,8 @@ if [ $LIST_VERSIONS -ne 0 ]; then # Read the user's desired Python version. # -r: treat backslashes as literal, -p: display prompt before input. read -r -p "Enter the desired Python version: " PYTHON_VERSION - # Check the Python versions being passed in. - if [ -n "${PYTHON_VERSION+x}" ]; then - if python_versions | grep -E "^${PYTHON_VERSION}$" > /dev/null; then - echo Using Python version "$PYTHON_VERSION" - else - echo Error: Python version "$PYTHON_VERSION" is not installed. - exit 1 - fi - fi + # Check the Python version being passed in. + check_python_version "$PYTHON_VERSION" fi # Remove any lingering local configuration. diff --git a/src/packer.pkr.hcl b/src/packer.pkr.hcl deleted file mode 100644 index 437adf07..00000000 --- a/src/packer.pkr.hcl +++ /dev/null @@ -1,210 +0,0 @@ -packer { - required_plugins { - amazon = { - source = "github.com/hashicorp/amazon" - version = "~> 1.2" - } - ansible = { - source = "github.com/hashicorp/ansible" - version = "~> 1.1" - } - } - # The required_plugins section is only supported in Packer 1.7.0 and - # later. We also want to avoid jumping to Packer v2 until we are - # ready. - required_version = "~> 1.7" -} - -variable "ami_regions" { - default = [] - description = "The list of AWS regions to copy the AMI to once it has been created. Example: [\"us-east-1\"]" - type = list(string) -} - -variable "build_region" { - default = "us-east-1" - description = "The region in which to retrieve the base AMI from and build the new AMI." - type = string -} - -variable "build_region_kms" { - default = "alias/cool-amis" - description = "The ID or ARN of the KMS key to use for AMI encryption." - type = string -} - -variable "is_prerelease" { - default = false - description = "The pre-release status to use for the tags applied to the created AMI." - type = bool -} - -variable "region_kms_keys" { - default = {} - description = "A map of regions to copy the created AMI to and the KMS keys to use for encryption in that region. The keys for this map must match the values provided to the aws_regions variable. Example: {\"us-east-1\": \"alias/example-kms\"}" - type = map(string) -} - -variable "release_tag" { - default = "" - description = "The GitHub release tag to use for the tags applied to the created AMI." - type = string -} - -variable "release_url" { - default = "" - description = "The GitHub release URL to use for the tags applied to the created AMI." - type = string -} - -variable "skip_create_ami" { - default = false - description = "Indicate if Packer should not create the AMI." - type = bool -} - -data "amazon-ami" "debian_bookworm_arm64" { - filters = { - architecture = "arm64" - name = "debian-12-arm64-*" - root-device-type = "ebs" - virtualization-type = "hvm" - } - most_recent = true - owners = ["136693071363"] - region = var.build_region -} - -data "amazon-ami" "debian_bookworm_x86_64" { - filters = { - architecture = "x86_64" - name = "debian-12-amd64-*" - root-device-type = "ebs" - virtualization-type = "hvm" - } - most_recent = true - owners = ["136693071363"] - region = var.build_region -} - -locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") } - -source "amazon-ebs" "arm64" { - ami_name = "example-hvm-${local.timestamp}-arm64-ebs" - ami_regions = var.ami_regions - associate_public_ip_address = true - encrypt_boot = true - instance_type = "t4g.small" - kms_key_id = var.build_region_kms - launch_block_device_mappings { - delete_on_termination = true - device_name = "/dev/xvda" - encrypted = true - volume_size = 8 - volume_type = "gp3" - } - region = var.build_region - region_kms_key_ids = var.region_kms_keys - skip_create_ami = var.skip_create_ami - source_ami = data.amazon-ami.debian_bookworm_arm64.id - ssh_username = "admin" - subnet_filter { - filters = { - "tag:Name" = "AMI Build" - } - } - tags = { - Application = "Example" - Architecture = "arm64" - Base_AMI_Name = data.amazon-ami.debian_bookworm_arm64.name - GitHub_Release_URL = var.release_url - OS_Version = "Debian Bookworm" - Pre_Release = var.is_prerelease - Release = var.release_tag - Team = "VM Fusion - Development" - } - # Many Linux distributions are now disallowing the use of RSA keys, - # so it makes sense to use an ED25519 key instead. - temporary_key_pair_type = "ed25519" - vpc_filter { - filters = { - "tag:Name" = "AMI Build" - } - } -} - -source "amazon-ebs" "x86_64" { - ami_name = "example-hvm-${local.timestamp}-x86_64-ebs" - ami_regions = var.ami_regions - associate_public_ip_address = true - encrypt_boot = true - instance_type = "t3.small" - kms_key_id = var.build_region_kms - launch_block_device_mappings { - delete_on_termination = true - device_name = "/dev/xvda" - encrypted = true - volume_size = 8 - volume_type = "gp3" - } - region = var.build_region - region_kms_key_ids = var.region_kms_keys - skip_create_ami = var.skip_create_ami - source_ami = data.amazon-ami.debian_bookworm_x86_64.id - ssh_username = "admin" - subnet_filter { - filters = { - "tag:Name" = "AMI Build" - } - } - tags = { - Application = "Example" - Architecture = "x86_64" - Base_AMI_Name = data.amazon-ami.debian_bookworm_x86_64.name - GitHub_Release_URL = var.release_url - OS_Version = "Debian Bookworm" - Pre_Release = var.is_prerelease - Release = var.release_tag - Team = "VM Fusion - Development" - } - # Many Linux distributions are now disallowing the use of RSA keys, - # so it makes sense to use an ED25519 key instead. - temporary_key_pair_type = "ed25519" - vpc_filter { - filters = { - "tag:Name" = "AMI Build" - } - } -} - -build { - sources = [ - "source.amazon-ebs.arm64", - "source.amazon-ebs.x86_64", - ] - - provisioner "ansible" { - playbook_file = "src/upgrade.yml" - use_proxy = false - use_sftp = true - } - - provisioner "ansible" { - playbook_file = "src/python.yml" - use_proxy = false - use_sftp = true - } - - provisioner "ansible" { - ansible_env_vars = ["AWS_DEFAULT_REGION=${var.build_region}"] - playbook_file = "src/playbook.yml" - use_proxy = false - use_sftp = true - } - - provisioner "shell" { - execute_command = "chmod +x {{ .Path }}; sudo env {{ .Vars }} {{ .Path }} ; rm -f {{ .Path }}" - inline = ["sed -i '/^users:/ {N; s/users:.*/users: []/g}' /etc/cloud/cloud.cfg", "rm --force /etc/sudoers.d/90-cloud-init-users", "rm --force /root/.ssh/authorized_keys", "/usr/sbin/userdel --remove --force admin"] - skip_clean = true - } -} diff --git a/tests/test_version.py b/tests/test_version.py index b4181dda..7196fa4f 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,4 +1,3 @@ -#!/usr/bin/env pytest -vs """Version tests for packer skeleton project.""" # Standard Python Libraries @@ -8,7 +7,7 @@ import pytest GITHUB_RELEASE_TAG = os.getenv("GITHUB_RELEASE_TAG") -VERSION_FILE = "src/version.txt" +VERSION_FILE = "version.txt" @pytest.mark.skipif( diff --git a/variables.pkr.hcl b/variables.pkr.hcl new file mode 100644 index 00000000..7df066f0 --- /dev/null +++ b/variables.pkr.hcl @@ -0,0 +1,59 @@ +# ------------------------------------------------------------------------------ +# Required parameters +# +# You must provide a value for each of these parameters. +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# Optional parameters +# +# These parameters have reasonable defaults. +# ------------------------------------------------------------------------------ + +variable "ami_regions" { + default = [] + description = "The list of AWS regions to copy the AMI to once it has been created. Example: [\"us-east-1\"]" + type = list(string) +} + +variable "build_region" { + default = "us-east-1" + description = "The region in which to retrieve the base AMI from and build the new AMI." + type = string +} + +variable "build_region_kms" { + default = "alias/cool-amis" + description = "The ID or ARN of the KMS key to use for AMI encryption." + type = string +} + +variable "is_prerelease" { + default = false + description = "The pre-release status to use for the tags applied to the created AMI." + type = bool +} + +variable "region_kms_keys" { + default = {} + description = "A map of regions to copy the created AMI to and the KMS keys to use for encryption in that region. The keys for this map must match the values provided to the aws_regions variable. Example: {\"us-east-1\": \"alias/example-kms\"}" + type = map(string) +} + +variable "release_tag" { + default = "" + description = "The GitHub release tag to use for the tags applied to the created AMI." + type = string +} + +variable "release_url" { + default = "" + description = "The GitHub release URL to use for the tags applied to the created AMI." + type = string +} + +variable "skip_create_ami" { + default = false + description = "Indicate if Packer should not create the AMI." + type = bool +} diff --git a/src/version.txt b/version.txt similarity index 100% rename from src/version.txt rename to version.txt diff --git a/versions.pkr.hcl b/versions.pkr.hcl new file mode 100644 index 00000000..9017550e --- /dev/null +++ b/versions.pkr.hcl @@ -0,0 +1,16 @@ +packer { + required_plugins { + amazon = { + source = "github.com/hashicorp/amazon" + version = "~> 1.2" + } + ansible = { + source = "github.com/hashicorp/ansible" + version = "~> 1.1" + } + } + # The required_plugins section is only supported in Packer 1.7.0 and + # later. We also want to avoid jumping to Packer v2 until we are + # ready. + required_version = "~> 1.7" +}