mirror of
https://github.com/bitwarden/self-host.git
synced 2026-06-28 06:15:46 +00:00
support for AWS marketplace (#477)
This commit is contained in:
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -18,5 +18,7 @@
|
||||
bitwarden-lite/ @bitwarden/dept-shot
|
||||
|
||||
# Release workflows
|
||||
.github/workflows/release-aws.yml @bitwarden/dept-bre
|
||||
.github/workflows/release-azure.yml @bitwarden/dept-bre
|
||||
.github/workflows/release-digital-ocean.yml @bitwarden/dept-bre
|
||||
.github/workflows/release.yml @bitwarden/dept-bre
|
||||
|
||||
168
.github/workflows/release-aws.yml
vendored
Normal file
168
.github/workflows/release-aws.yml
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
name: Release AWS Marketplace
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
push:
|
||||
paths:
|
||||
- "AWSMarketplace/**"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-image:
|
||||
name: Build Image
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 90
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Log in to Azure
|
||||
uses: bitwarden/gh-actions/azure-login@main
|
||||
with:
|
||||
subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
tenant_id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client_id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
with:
|
||||
keyvault: "gh-self-host"
|
||||
secrets: "aws-marketplace-access-key-id,
|
||||
aws-marketplace-secret-access-key"
|
||||
|
||||
- name: Log out from Azure
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
|
||||
- name: Set version from version.json
|
||||
id: set-version
|
||||
run: |
|
||||
VERSION=$(jq -r '.versions.coreVersion' version.json)
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "ERROR: Failed to extract coreVersion from version.json"
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set up Hashicorp Packer
|
||||
uses: hashicorp/setup-packer@1aa358be5cf73883762b302a3a03abd66e75b232 # v3.1.0
|
||||
|
||||
- name: Build AWS Image
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-marketplace-access-key-id }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-marketplace-secret-access-key }}
|
||||
AWS_DEFAULT_REGION: "us-east-1"
|
||||
AWS_IMG_VERSION: ${{ steps.set-version.outputs.version }}
|
||||
working-directory: ./AWSMarketplace
|
||||
run: |
|
||||
packer version
|
||||
packer init -upgrade marketplace-image.pkr.hcl
|
||||
packer build marketplace-image.pkr.hcl
|
||||
|
||||
- name: Cleanup orphaned instances on cancellation or failure
|
||||
if: cancelled() || failure()
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-marketplace-access-key-id }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-marketplace-secret-access-key }}
|
||||
AWS_DEFAULT_REGION: "us-east-1"
|
||||
run: |
|
||||
echo "Workflow cancelled - cleaning up any orphaned resources..."
|
||||
|
||||
echo "## :warning: Workflow Cancelled - Resource Cleanup" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Searching for orphaned instances with tag: \`github-run-${{ github.run_id }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Find and terminate EC2 instances tagged with this run
|
||||
INSTANCE_IDS=$(aws ec2 describe-instances \
|
||||
--filters "Name=tag:GitHub_Run,Values=github-run-${{ github.run_id }}" \
|
||||
"Name=instance-state-name,Values=pending,running,stopping,stopped" \
|
||||
--query "Reservations[].Instances[].InstanceId" \
|
||||
--output text)
|
||||
|
||||
if [ -n "$INSTANCE_IDS" ]; then
|
||||
echo "Found orphaned instances: $INSTANCE_IDS"
|
||||
echo "### Orphaned Instances Found and Terminated" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Instance ID | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|-------------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
for INSTANCE_ID in $INSTANCE_IDS; do
|
||||
echo "Terminating instance: $INSTANCE_ID"
|
||||
if aws ec2 terminate-instances --instance-ids "$INSTANCE_ID"; then
|
||||
echo "| $INSTANCE_ID | :white_check_mark: Terminated |" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "| $INSTANCE_ID | :x: Failed to terminate |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "No orphaned instances found"
|
||||
echo ":white_check_mark: No orphaned resources found - nothing to clean up" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: Add build summary
|
||||
if: success()
|
||||
env:
|
||||
VERSION: ${{ steps.set-version.outputs.version }}
|
||||
working-directory: ./AWSMarketplace
|
||||
run: |
|
||||
echo "## :rocket: AWS Marketplace Image Build Complete" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Version:** ${VERSION}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Get artifact details from manifest
|
||||
if [ -f manifest.json ]; then
|
||||
AMI_ID=$(jq -r '.builds[-1].artifact_id' manifest.json)
|
||||
echo "**AMI ID:** \`$AMI_ID\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo ":white_check_mark: Packer build instance was automatically cleaned up" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: AWS Image Cleanup
|
||||
working-directory: ./AWSMarketplace
|
||||
if: ${{ github.event_name != 'release' && github.event_name != 'workflow_dispatch' }}
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-marketplace-access-key-id }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-marketplace-secret-access-key }}
|
||||
AWS_DEFAULT_REGION: "us-east-1"
|
||||
run: |
|
||||
# Get the AMI ID from the manifest (format: "us-east-1:ami-xxxxxxxxx")
|
||||
AMI_ID=$(jq -r '.builds[-1].artifact_id' manifest.json | cut -d ":" -f2)
|
||||
|
||||
if [ -n "$AMI_ID" ]; then
|
||||
# Find associated snapshots before deregistering
|
||||
SNAPSHOT_IDS=$(aws ec2 describe-images --image-ids "$AMI_ID" \
|
||||
--query "Images[].BlockDeviceMappings[].Ebs.SnapshotId" \
|
||||
--output text 2>/dev/null || true)
|
||||
|
||||
# Deregister the AMI
|
||||
aws ec2 deregister-image --image-id "$AMI_ID" 2>/dev/null || true
|
||||
|
||||
# Delete associated snapshots
|
||||
for SNAPSHOT_ID in $SNAPSHOT_IDS; do
|
||||
aws ec2 delete-snapshot --snapshot-id "$SNAPSHOT_ID" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
|
||||
# Update summary for non-release builds
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "---" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo ":wastebasket: **Non-release build:** AMI \`$AMI_ID\` and snapshots were automatically cleaned up" >> $GITHUB_STEP_SUMMARY
|
||||
15
.github/workflows/release.yml
vendored
15
.github/workflows/release.yml
vendored
@@ -529,3 +529,18 @@ jobs:
|
||||
ref: process.env.RELEASE_TAG,
|
||||
inputs: {}
|
||||
});
|
||||
|
||||
- name: Trigger release-aws workflow
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
RELEASE_TAG: v${{ inputs.release_version }}
|
||||
with:
|
||||
github-token: ${{ steps.app-token.outputs.token }}
|
||||
script: |
|
||||
await github.rest.actions.createWorkflowDispatch({
|
||||
owner: 'bitwarden',
|
||||
repo: 'self-host',
|
||||
workflow_id: 'release-aws.yml',
|
||||
ref: process.env.RELEASE_TAG,
|
||||
inputs: {}
|
||||
});
|
||||
|
||||
16
AWSMarketplace/files/etc/profile.d/bitwarden-install.sh
Normal file
16
AWSMarketplace/files/etc/profile.d/bitwarden-install.sh
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# First-login trigger for Bitwarden installation.
|
||||
# This script runs once on the first interactive login, then removes itself.
|
||||
# Skip for the bitwarden service account (it doesn't have sudo).
|
||||
|
||||
if [ "$(whoami)" = "bitwarden" ]; then
|
||||
return 0 2>/dev/null || exit 0
|
||||
fi
|
||||
|
||||
if [ -f /opt/bitwarden/install-bitwarden.sh ]; then
|
||||
# Wait for cloud-init to finish (downloads bitwarden.sh on first boot)
|
||||
echo "Waiting for cloud-init to complete..."
|
||||
sudo cloud-init status --wait > /dev/null 2>&1
|
||||
sudo /opt/bitwarden/install-bitwarden.sh
|
||||
fi
|
||||
4
AWSMarketplace/files/etc/ufw/applications.d/bitwarden
Normal file
4
AWSMarketplace/files/etc/ufw/applications.d/bitwarden
Normal file
@@ -0,0 +1,4 @@
|
||||
[Bitwarden]
|
||||
title=Bitwarden server
|
||||
description=Bitwarden is an open source password management tool that allows you to securely store, share, and sync passwords and other senitive data.
|
||||
ports=80/tcp|443/tcp
|
||||
26
AWSMarketplace/files/etc/update-motd.d/99-bitwarden-welcome
Normal file
26
AWSMarketplace/files/etc/update-motd.d/99-bitwarden-welcome
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Configured as part of the AWS Marketplace Image build process
|
||||
|
||||
myip=$(hostname -I | awk '{print$1}')
|
||||
cat <<EOF
|
||||
********************************************************************************
|
||||
|
||||
Welcome to your Bitwarden server
|
||||
https://bitwarden.com
|
||||
|
||||
Complete documentation:
|
||||
https://help.bitwarden.com/hosting/
|
||||
|
||||
Configuration:
|
||||
Configuration changes can be made in /home/bitwarden/bwdata/config.yml and
|
||||
/home/bitwarden/bwdata/env/global.override.env
|
||||
|
||||
Common commands:
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh stop
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh restart
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh rebuild
|
||||
|
||||
********************************************************************************
|
||||
To delete this message of the day: rm -rf $(readlink -f ${0})
|
||||
EOF
|
||||
48
AWSMarketplace/files/opt/bitwarden/install-bitwarden.sh
Normal file
48
AWSMarketplace/files/opt/bitwarden/install-bitwarden.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Install Bitwarden
|
||||
# ref: https://help.bitwarden.com/article/install-on-premise/
|
||||
#
|
||||
|
||||
echo -e ''
|
||||
echo -e 'Installing Bitwarden...'
|
||||
echo -e ''
|
||||
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh install
|
||||
|
||||
echo -e ''
|
||||
echo -e 'Starting Bitwarden containers...'
|
||||
echo -e ''
|
||||
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh start
|
||||
|
||||
echo -e ''
|
||||
echo -e 'Waiting for Bitwarden database container to come online...'
|
||||
|
||||
sleep 30s
|
||||
|
||||
echo -e 'Initializing Bitwarden database...'
|
||||
echo -e ''
|
||||
|
||||
sudo -i -u bitwarden /home/bitwarden/bitwarden.sh updatedb
|
||||
|
||||
echo -e ''
|
||||
echo -e 'Bitwarden installation complete.'
|
||||
echo -e ''
|
||||
|
||||
#
|
||||
# Setup Bitwarden update cron
|
||||
# ref: https://help.bitwarden.com/article/updating-on-premise/
|
||||
#
|
||||
|
||||
echo -e '#!/usr/bin/env bash\nsudo -i -u bitwarden /home/bitwarden/bitwarden.sh updateself\nsudo -i -u bitwarden /home/bitwarden/bitwarden.sh update' \
|
||||
> /etc/cron.weekly/bitwardenupdate
|
||||
|
||||
chmod +x /etc/cron.weekly/bitwardenupdate
|
||||
|
||||
#
|
||||
# Cleanup - remove the login trigger
|
||||
#
|
||||
|
||||
rm -f /etc/profile.d/bitwarden-install.sh
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Scripts in this directory will be executed by cloud-init on the first boot of instances
|
||||
# created from your image. Things like generating passwords, configuration requiring IP address
|
||||
# or other items that will be unique to each instance should be done in scripts here.
|
||||
|
||||
#
|
||||
# Setup Bitwarden Installer
|
||||
# ref: https://help.bitwarden.com/article/install-on-premise/
|
||||
#
|
||||
|
||||
docker pull ghcr.io/bitwarden/setup
|
||||
|
||||
curl -L -s -o /home/bitwarden/bitwarden.sh "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux"
|
||||
|
||||
chmod +x /home/bitwarden/bitwarden.sh
|
||||
chown bitwarden:bitwarden /home/bitwarden/bitwarden.sh
|
||||
169
AWSMarketplace/marketplace-image.pkr.hcl
Normal file
169
AWSMarketplace/marketplace-image.pkr.hcl
Normal file
@@ -0,0 +1,169 @@
|
||||
packer {
|
||||
required_plugins {
|
||||
amazon = {
|
||||
version = ">= 1.2.0"
|
||||
source = "github.com/hashicorp/amazon"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
variable "application_name" {
|
||||
type = string
|
||||
default = "Bitwarden"
|
||||
}
|
||||
|
||||
variable "application_version" {
|
||||
type = string
|
||||
default = "${env("AWS_IMG_VERSION")}"
|
||||
}
|
||||
|
||||
variable "apt_packages" {
|
||||
type = string
|
||||
default = "fail2ban ca-certificates curl gnupg"
|
||||
}
|
||||
|
||||
variable "docker_packages" {
|
||||
type = string
|
||||
default = "docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
|
||||
}
|
||||
|
||||
variable "aws_region" {
|
||||
type = string
|
||||
default = "us-east-1"
|
||||
}
|
||||
|
||||
variable "github_run_id" {
|
||||
type = string
|
||||
default = "${env("GITHUB_RUN_ID")}"
|
||||
}
|
||||
|
||||
# "timestamp" template function replacement
|
||||
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
|
||||
|
||||
locals {
|
||||
image_name = "bitwarden-22-04-${local.timestamp}"
|
||||
}
|
||||
|
||||
source "amazon-ebs" "bitwarden_self_host" {
|
||||
region = var.aws_region
|
||||
instance_type = "t3.small"
|
||||
ssh_username = "ubuntu"
|
||||
|
||||
source_ami_filter {
|
||||
filters = {
|
||||
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
|
||||
root-device-type = "ebs"
|
||||
virtualization-type = "hvm"
|
||||
}
|
||||
most_recent = true
|
||||
owners = ["099720109477"] # Canonical
|
||||
}
|
||||
|
||||
ami_name = local.image_name
|
||||
ami_description = "Bitwarden Self-Host ${var.application_version}"
|
||||
|
||||
tags = {
|
||||
Name = local.image_name
|
||||
Application = "bitwarden-packer-build"
|
||||
Version = var.application_version
|
||||
GitHub_Run = "github-run-${var.github_run_id}"
|
||||
}
|
||||
|
||||
run_tags = {
|
||||
Name = "packer-bitwarden-${var.github_run_id}"
|
||||
Application = "bitwarden-packer-build"
|
||||
GitHub_Run = "github-run-${var.github_run_id}"
|
||||
}
|
||||
}
|
||||
|
||||
build {
|
||||
sources = ["source.amazon-ebs.bitwarden_self_host"]
|
||||
|
||||
provisioner "shell" {
|
||||
inline = ["cloud-init status --wait"]
|
||||
}
|
||||
|
||||
# Upload individual files to /tmp staging area (amazon-ebs connects as a non-root user)
|
||||
provisioner "file" {
|
||||
source = "files/etc/update-motd.d/99-bitwarden-welcome"
|
||||
destination = "/tmp/99-bitwarden-welcome"
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "files/etc/ufw/applications.d/bitwarden"
|
||||
destination = "/tmp/bitwarden-ufw"
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "files/opt/bitwarden/install-bitwarden.sh"
|
||||
destination = "/tmp/install-bitwarden.sh"
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "files/var/lib/cloud/scripts/per-instance/001_onboot"
|
||||
destination = "/tmp/001_onboot"
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "files/etc/profile.d/bitwarden-install.sh"
|
||||
destination = "/tmp/bitwarden-install.sh"
|
||||
}
|
||||
|
||||
# Move staged files to their final system locations
|
||||
provisioner "shell" {
|
||||
inline = [
|
||||
"sudo mkdir -p /etc/update-motd.d /etc/ufw/applications.d /opt/bitwarden /var/lib/cloud/scripts/per-instance",
|
||||
"sudo mv /tmp/99-bitwarden-welcome /etc/update-motd.d/99-bitwarden-welcome",
|
||||
"sudo mv /tmp/bitwarden-ufw /etc/ufw/applications.d/bitwarden",
|
||||
"sudo mv /tmp/install-bitwarden.sh /opt/bitwarden/install-bitwarden.sh",
|
||||
"sudo mv /tmp/001_onboot /var/lib/cloud/scripts/per-instance/001_onboot",
|
||||
"sudo mv /tmp/bitwarden-install.sh /etc/profile.d/bitwarden-install.sh",
|
||||
"sudo chown root:root /etc/update-motd.d/99-bitwarden-welcome /etc/ufw/applications.d/bitwarden /opt/bitwarden/install-bitwarden.sh /var/lib/cloud/scripts/per-instance/001_onboot /etc/profile.d/bitwarden-install.sh",
|
||||
"sudo chmod 644 /etc/ufw/applications.d/bitwarden /etc/profile.d/bitwarden-install.sh"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "shell" {
|
||||
environment_vars = [
|
||||
"DEBIAN_FRONTEND=noninteractive",
|
||||
"LC_ALL=C",
|
||||
"LANG=en_US.UTF-8",
|
||||
"LC_CTYPE=en_US.UTF-8"
|
||||
]
|
||||
inline = [
|
||||
"sudo apt-get -qqy update",
|
||||
"sudo apt-get -qqy -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' full-upgrade",
|
||||
"sudo apt-get -qqy -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' install ${var.apt_packages}",
|
||||
"sudo install -m 0755 -d /etc/apt/keyrings",
|
||||
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg",
|
||||
"sudo chmod a+r /etc/apt/keyrings/docker.gpg",
|
||||
"echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null",
|
||||
"sudo apt-get -qqy update",
|
||||
"sudo apt-get -qqy -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold' install ${var.docker_packages}",
|
||||
"sudo apt-get -qqy clean"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "shell" {
|
||||
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E bash '{{ .Path }}'"
|
||||
environment_vars = [
|
||||
"application_name=${var.application_name}",
|
||||
"application_version=${var.application_version}",
|
||||
"DEBIAN_FRONTEND=noninteractive",
|
||||
"LC_ALL=C",
|
||||
"LANG=en_US.UTF-8",
|
||||
"LC_CTYPE=en_US.UTF-8"
|
||||
]
|
||||
scripts = [
|
||||
"scripts/01-setup-first-run.sh",
|
||||
"scripts/02-ufw-bitwarden.sh",
|
||||
"scripts/90-cleanup.sh",
|
||||
"scripts/99-img-check.sh"
|
||||
]
|
||||
}
|
||||
|
||||
post-processor "manifest" {
|
||||
output = "manifest.json"
|
||||
strip_path = true
|
||||
}
|
||||
}
|
||||
29
AWSMarketplace/scripts/01-setup-first-run.sh
Normal file
29
AWSMarketplace/scripts/01-setup-first-run.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Scripts in this directory are run during the build process.
|
||||
# Each script will be uploaded to /tmp on your build instance,
|
||||
# given execute permissions and run. The cleanup process will
|
||||
# remove the scripts from your build system after they have run
|
||||
# if you use the build_image task.
|
||||
#
|
||||
|
||||
#
|
||||
# Create dedicated bitwarden user with Docker access
|
||||
#
|
||||
|
||||
useradd -m -s /bin/bash bitwarden
|
||||
usermod -aG docker bitwarden
|
||||
|
||||
#
|
||||
# Make MOTD and boot script executable
|
||||
#
|
||||
|
||||
chmod +x /var/lib/cloud/scripts/per-instance/001_onboot
|
||||
|
||||
chmod +x /etc/update-motd.d/99-bitwarden-welcome
|
||||
|
||||
#
|
||||
# Setup First Run Script
|
||||
#
|
||||
|
||||
chmod +x /opt/bitwarden/install-bitwarden.sh
|
||||
6
AWSMarketplace/scripts/02-ufw-bitwarden.sh
Normal file
6
AWSMarketplace/scripts/02-ufw-bitwarden.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
ufw allow ssh
|
||||
ufw allow 'Bitwarden'
|
||||
|
||||
ufw --force enable
|
||||
29
AWSMarketplace/scripts/90-cleanup.sh
Normal file
29
AWSMarketplace/scripts/90-cleanup.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# AWS Marketplace Image Cleanup
|
||||
|
||||
set -o errexit
|
||||
|
||||
# Ensure /tmp exists and has the proper permissions
|
||||
if [ ! -d /tmp ]; then
|
||||
mkdir /tmp
|
||||
fi
|
||||
chmod 1777 /tmp
|
||||
|
||||
if [ -n "$(command -v apt-get)" ]; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -y update
|
||||
apt-get -o Dpkg::Options::="--force-confold" upgrade -q -y
|
||||
apt-get -y autoremove
|
||||
apt-get -y autoclean
|
||||
fi
|
||||
|
||||
rm -rf /tmp/* /var/tmp/*
|
||||
cat /dev/null > /root/.bash_history
|
||||
unset HISTFILE
|
||||
find /var/log -mtime -1 -type f -exec truncate -s 0 {} \;
|
||||
rm -rf /var/log/*.gz /var/log/*.[0-9] /var/log/*-????????
|
||||
rm -rf /var/lib/cloud/instances/*
|
||||
rm -f /root/.ssh/authorized_keys /etc/ssh/*key*
|
||||
touch /etc/ssh/revoked_keys
|
||||
chmod 600 /etc/ssh/revoked_keys
|
||||
162
AWSMarketplace/scripts/99-img-check.sh
Normal file
162
AWSMarketplace/scripts/99-img-check.sh
Normal file
@@ -0,0 +1,162 @@
|
||||
#!/bin/bash
|
||||
|
||||
# AWS Marketplace Image Validation Tool
|
||||
|
||||
VERSION="v. 1.0.0"
|
||||
RUNDATE=$( date )
|
||||
|
||||
# Script should be run with SUDO
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "[Error] - This script must be run with sudo or as the root user."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
STATUS=0
|
||||
PASS=0
|
||||
WARN=0
|
||||
FAIL=0
|
||||
|
||||
clear
|
||||
echo "AWS Marketplace Image Validation Tool ${VERSION}"
|
||||
echo "Executed on: ${RUNDATE}"
|
||||
echo "Checking local system for Marketplace compatibility..."
|
||||
echo ""
|
||||
|
||||
# Check OS
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$NAME
|
||||
VER=$VERSION_ID
|
||||
else
|
||||
OS=$(uname -s)
|
||||
VER=$(uname -r)
|
||||
fi
|
||||
|
||||
echo -en "Distribution: ${OS}\n"
|
||||
echo -en "Version: ${VER}\n\n"
|
||||
|
||||
if [[ $OS == "Ubuntu" ]] && [[ $VER == "22.04" ]]; then
|
||||
echo -en "\e[32m[PASS]\e[0m Supported OS detected: ${OS} ${VER}\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[41m[FAIL]\e[0m ${OS} ${VER} is not the expected OS (Ubuntu 22.04)\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
fi
|
||||
|
||||
# Check cloud-init
|
||||
if hash cloud-init 2>/dev/null; then
|
||||
echo -en "\e[32m[PASS]\e[0m Cloud-init is installed.\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[41m[FAIL]\e[0m Cloud-init is not installed.\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
fi
|
||||
|
||||
# Check Docker
|
||||
if hash docker 2>/dev/null; then
|
||||
echo -en "\e[32m[PASS]\e[0m Docker is installed.\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[41m[FAIL]\e[0m Docker is not installed.\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
fi
|
||||
|
||||
# Check firewall
|
||||
if [[ $OS == "Ubuntu" ]]; then
|
||||
ufwa=$(ufw status | head -1 | sed -e "s/^Status:\ //")
|
||||
if [[ $ufwa == "active" ]]; then
|
||||
echo -en "\e[32m[PASS]\e[0m Firewall (ufw) is active.\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[93m[WARN]\e[0m Firewall (ufw) is not active.\n"
|
||||
((WARN++))
|
||||
if [[ $STATUS != 2 ]]; then STATUS=1; fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check root password
|
||||
SHADOW=$(cat /etc/shadow)
|
||||
for usr in $SHADOW; do
|
||||
IFS=':' read -r -a u <<< "$usr"
|
||||
if [[ "${u[0]}" == "root" ]]; then
|
||||
if [[ ${u[1]} == "!" ]] || [[ ${u[1]} == "!!" ]] || [[ ${u[1]} == "*" ]]; then
|
||||
echo -en "\e[32m[PASS]\e[0m Root user has no password set.\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[41m[FAIL]\e[0m Root user has a password set.\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Check SSH keys
|
||||
if [ -f /root/.ssh/authorized_keys ] && [ "$(wc -c < /root/.ssh/authorized_keys)" -gt 50 ]; then
|
||||
echo -en "\e[41m[FAIL]\e[0m Root has a populated authorized_keys file.\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
else
|
||||
echo -en "\e[32m[PASS]\e[0m No SSH keys found for root.\n"
|
||||
((PASS++))
|
||||
fi
|
||||
|
||||
# Check bash history
|
||||
if [ -f /root/.bash_history ]; then
|
||||
BH_S=$(wc -c < /root/.bash_history)
|
||||
if [[ $BH_S -lt 200 ]]; then
|
||||
echo -en "\e[32m[PASS]\e[0m Root bash history appears cleared.\n"
|
||||
((PASS++))
|
||||
else
|
||||
echo -en "\e[41m[FAIL]\e[0m Root bash history should be cleared.\n"
|
||||
((FAIL++))
|
||||
STATUS=2
|
||||
fi
|
||||
else
|
||||
echo -en "\e[32m[PASS]\e[0m Root bash history is not present.\n"
|
||||
((PASS++))
|
||||
fi
|
||||
|
||||
# Check for log files
|
||||
echo -en "\nChecking for log files in /var/log\n"
|
||||
for f in /var/log/*-????????; do
|
||||
[[ -e $f ]] || break
|
||||
echo -en "\e[93m[WARN]\e[0m Log archive ${f} found.\n"
|
||||
((WARN++))
|
||||
if [[ $STATUS != 2 ]]; then STATUS=1; fi
|
||||
done
|
||||
for f in /var/log/*.[0-9]; do
|
||||
[[ -e $f ]] || break
|
||||
echo -en "\e[93m[WARN]\e[0m Log archive ${f} found.\n"
|
||||
((WARN++))
|
||||
if [[ $STATUS != 2 ]]; then STATUS=1; fi
|
||||
done
|
||||
|
||||
# Summary
|
||||
echo -en "\n---------------------------------------------------------------------------------------------------\n"
|
||||
|
||||
if [[ $STATUS == 0 ]]; then
|
||||
echo -en "Scan Complete.\n\e[32mAll Tests Passed!\e[0m\n"
|
||||
elif [[ $STATUS == 1 ]]; then
|
||||
echo -en "Scan Complete.\n\e[93mSome non-critical tests failed. Please review these items.\e[0m\n"
|
||||
else
|
||||
echo -en "Scan Complete.\n\e[41mOne or more tests failed. Please review these items and re-test.\e[0m\n"
|
||||
fi
|
||||
echo "---------------------------------------------------------------------------------------------------"
|
||||
echo -en "\e[1m${PASS} Tests PASSED\e[0m\n"
|
||||
echo -en "\e[1m${WARN} WARNINGS\e[0m\n"
|
||||
echo -en "\e[1m${FAIL} Tests FAILED\e[0m\n"
|
||||
echo -en "---------------------------------------------------------------------------------------------------\n"
|
||||
|
||||
if [[ $STATUS == 0 ]]; then
|
||||
echo -en "No issues detected. Ensure all software is functional, secure, and properly configured.\n\n"
|
||||
exit 0
|
||||
elif [[ $STATUS == 1 ]]; then
|
||||
echo -en "Please review all [WARN] items above and ensure they are intended or resolved.\n\n"
|
||||
exit 0
|
||||
else
|
||||
echo -en "Critical tests failed. These must be resolved before submitting to AWS Marketplace.\n\n"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user