I'm trying to setup a CI pipeline on Github Actions that could support multiple aws accounts.
I have a "dev" account for deploying all the dev infrastructure and an "admin" account in which we manage terraform state (in an S3 bucket) for multiple projects, including this one.
So when deploying with CDKTF I must access with two accounts: one for the aws provider, that will perform the deploy, and another one to access the bucket holding the state.
I created two roles in the two accounts separately as explained on the aws-actions/configure-aws-credentials repository and configured the CI like this
- name: Configure AWS Credentials for Dev
uses: aws-actions/configure-aws-credentials#v1
with:
aws-region: $AWS_REGION
role-to-assume: ${{ secrets.CI_ROLE_ARN_DEV }}
role-session-name: dev-session
- name: Configure AWS Credentials for Admin
uses: aws-actions/configure-aws-credentials#v1
with:
aws-region: $AWS_REGION
role-to-assume: ${{ secrets.CI_ROLE_ARN_ADMIN }}
role-session-name: admin-session
But when running cdktf deploy I get the error failed to get shared config profile, dev where dev is the name of the profile specified in the AwsProvider like this
const provider = new AwsProvider(this, 'aws-provider', {
region: awsRegion,
profile: 'dev'
});
In fact, when executing aws sts get-caller-identity in GH Actions it outputs like it's logged as the admin account, becuse it's the last one I configured.
I don't know how I can tell Github to manage both accounts at the same time.
Keep in mind: when deploying locally, if I login via sso (aws sso login --profile <profile-name>) with both profiles, I can deploy everything with no problem at all.
Following another stackoverflow question (that I can't find right now), I tried configuring the profiles like this directly in the CI
- name: Configure aws credentials
run: |
aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID_DEV }} --profile dev
aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }} --profile dev
aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY_ID_ADMIN }} --profile admin
aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_ACCESS_KEY_ADMIN }} admin
cat "$AWS_SHARED_CREDENTIALS_FILE"
and despite it cating the right information, when cdktf deploying I get the following
error configuring S3 Backend: no valid credential sources for S3 Backend found.
Also when calling aws sts get-caller-identity on both profiles i always get
An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.
Using github actions I'm building a container and pushing it to an existing VM instance. I would like to include secrets as environmental variables after authenticating the secret manager so the container can utilize them during runtime. The following command updates the container to the VM but it does not accept any secrets as parameters.
- name: Deploy to google compute instance
run: |-
gcloud compute instances update-container ${{ env.GCE_INSTANCE }} \
--zone "$GCE_INSTANCE_ZONE" \
--container-image ${{ env.REGION}}-docker.pkg.dev/${{ secrets.PROJECT_ID}}/${{ env.ARTIFACT_REPO}}/${{ env.DOCKER_IMAGE }} \
In the past, I have deployed a docker container to google run and included secrets as environmental variables successfully with the following command. Is there a way to mimic this behavior from google run with a VM instance?
- name: deploy
id: 'deploy'
uses: 'google-github-actions/deploy-cloudrun#v0'
with:
service: ${{ env.IMAGE_NAME}}
image: ${{ env.REGION}}-docker.pkg.dev/${{ secrets.PROJECT_ID}}/${{ env.ARTIFACT_REPO}}/${{ env.DOCKER_IMAGE }}
region: ${{ env.REGION }}
secrets: |-
SQL_SERVER_CA=SQL_SERVER_CA:latest, SQL_CLIENT_CERT=SQL_CLIENT_CERT:latest
Following the advice of #JohnHanley 's comment, I was able to access secrets within my container that is running on a VM instance. Using --container-env flag on the "gcloud compute instances update-container" worked. The service account token for accessing secret manager is stored in github action secrets and it is base64 encoded. It is passed into the container with the --container-env flag along with two other variables. Once the container has started the service account token is decoded and used to retrieve the rest of the many secrets stored in google secrets manager. This likely is not the best way but it required the least amount of rework to get working.
- name: Deploy to google compute instance
run: |-
gcloud compute instances update-container ${{ env.GCE_INSTANCE }} \
--zone ${{ env.ZONE}} \
--container-image ${{ env.REGION}}-docker.pkg.dev/${{ secrets.PROJECT_ID}}/${{ env.ARTIFACT_REPO}}/${{ env.DOCKER_IMAGE }} \
--container-env GCP_SECRET_ACCESSOR_SERVICE_TOKEN=${{ secrets.GCP_SECRET_ACCESSOR_SERVICE_TOKEN}} \
--container-env PROJECT_ID=${{ secrets.PROJECT_ID}} \
--container-env RUNNING_LOCATION=cloudbt
You can use Cloud Build to inject the secrets. For that, you need to:
1.Enable the Cloud Build and Secret Manager APIs.
2.Set up the required IAM permissions.
3.Configure builds to access UTF-8 secrets from Secret Manager. As an example, the following build YAML shows how to login to Docker using the Docker username and password stored in Secret Manager:
steps:
- name: 'gcr.io/cloud-builders/docker'
entrypoint: 'bash'
args: ['-c', 'docker login --username=$$USERNAME --password=$$PASSWORD']
secretEnv: ['USERNAME', 'PASSWORD']
availableSecrets:
secretManager:
- versionName: projects/PROJECT_ID/secrets/DOCKER_PASSWORD_SECRET_NAME/versions/DOCKER_PASSWORD_SECRET_VERSION
env: 'PASSWORD'
- versionName: projects/PROJECT_ID/secrets/DOCKER_USERNAME_SECRET_NAME/versions/DOCKER_USERNAME_SECRET_VERSION
env: 'USERNAME'
Use this Official GCP's Documentation as a more detailed reference for that; it has Docker and GitHub examples.
Plus, there is another 3rd-party option useful for you: SecretHub. Here, you have the required steps that you need to follow using SecretHub.
Use this last thread Can I run a Cloud build on my own VM intances as another Cloud Build reference on GCP's VMs.
And finally, on this Official GCP’s Documentation you are going to find the information and steps to implement Caching in Cloud Build, to speed up your build as you need to do it.
i am new github actions workflow and was wondering that is it possible that i set my ec2 machine directly for CI and CD after every push.
I have seen that it is possible with ECS , but i wanted a straight forward solution as we are trying this out on our Dev environment we don't want over shoot our budget.
is it possible , if yes how can i achieve it ?
If you build your code in GitHub Actions, and just want to copy the package over existing EC2, you can use SCP files action plugin
https://github.com/marketplace/actions/scp-files
- name: copy file via ssh key
uses: appleboy/scp-action#master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
port: ${{ secrets.PORT }}
key: ${{ secrets.KEY }}
source: "tests/a.txt,tests/b.txt"
target: "test"
If you have any other AWS resource which interacts with EC2 (or any other AWS service) and you want to use AWS CLI, you can use AWS Credentials Action
https://github.com/aws-actions/configure-aws-credentials
- name: Configure AWS credentials from Test account
uses: aws-actions/configure-aws-credentials#v1
with:
aws-access-key-id: ${{ secrets.TEST_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.TEST_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Copy files to the test website with the AWS CLI
run: |
aws s3 sync . s3://my-s3-test-website-bucket
Here there is a nice article. The goal of article is to build a CI/CD stack with Github Actions + AWS EC2, CodeDeploy and S3.
As the title says I am trying to deploy my Laravel-Angular application directly from Github to AWS EC2 instance using Github Actions.
In my application there are 3 Angular 8+ projects which are needed to be build before deployment. Where as laravel does not need to be build.
The solutions that are available suggests to use AWS Elastic Beanstalk to deploy code. But, if that is to be done how to attach an elastic beanstalk to an existing instance is not clear enough.
Is there a way to deploy code to AWS EC2 without using Elastic Beanstalk?
Here is my Github Actions build.yml :
name: Build Develop Branch
on:
push:
branches: [ develop ]
pull_request:
branches: [ develop ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- name: Code Checkout
uses: actions/checkout#v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node#v1
with:
node-version: ${{ matrix.node-version }}
- name: App 1 npm install
run: npm install
working-directory: angular-app-1
- name: App 1 Build
run: npm run build:staging
working-directory: angular-app-1
- name: App 2 npm install
run: npm install
working-directory: angular-app-2
- name: App 2 Build
run: node node_modules/#angular/cli/bin/ng build --configuration=staging
working-directory: angular-app-2
- name: App 3 npm install
run: npm install
working-directory: angular-app-3
- name: App 3 Build
run: node node_modules/#angular/cli/bin/ng build --configuration=staging
working-directory: angular-app-3
Is there a way to deploy code to AWS EC2 without using Elastic Beanstalk?
I found a simple way to deploy to EC2 instance (or to any server that accepts rsync commands over ssh) using GitHub Actions.
I have a simple file in the repo's .github/workflows folder, which GitHub Actions runs to deploy to my EC2 instance whenever a push is made to my GitHub repo.
No muss, no fuss, no special incantations or Byzantine AWS configuration details.
File .github/workflows/pushtoec2.yml:
name: Push-to-EC2
on: push
jobs:
deploy:
name: Push to EC2 Instance
runs-on: ubuntu-latest
steps:
- name: Checkout the code
uses: actions/checkout#v1
- name: Deploy to my EC2 instance
uses: easingthemes/ssh-deploy#v2.1.5
env:
SSH_PRIVATE_KEY: ${{ secrets.EC2_SSH_KEY }}
SOURCE: "./"
REMOTE_HOST: "ec2-34-213-48-149.us-west-2.compute.amazonaws.com"
REMOTE_USER: "ec2-user"
TARGET: "/home/ec2-user/SampleExpressApp"
Details of the ssh deploy GitHub Action, used above.
Real final edit
A year later, I finally got around to making the tutorial: https://github.com/Andrew-Chen-Wang/cookiecutter-django-ec2-github.
I found a Medium tutorial that also deserves some light if anyone wants to use Code Pipeline (there's a couple of differences; I store my files on GitHub while the Medium tutorial is on S3. I create a custom VPC that the other author doesn't).
Earlier final edit
AWS has finally made a neat tutorial for CodeDeploy w/ GitHub repository: https://docs.aws.amazon.com/codedeploy/latest/userguide/tutorials-github-prerequisites.html take a look there and enjoy :)
Like the ECS tutorial, we're using Parameter Store to store our secrets. The way AWS previous wanted us to grab secrets was via a script in a bash script: https://aws.amazon.com/blogs/mt/use-parameter-store-to-securely-access-secrets-and-config-data-in-aws-codedeploy/
For example:
password=$(aws ssm get-parameters --region us-east-1 --names MySecureSQLPassword --with-decryption --query Parameters[0].Value)
password=`echo $password | sed -e 's/^"//' -e 's/"$//'`
mysqladmin -u root password $password
New edit (24 December 2020): I think I've nailed it. Below I pointed to Donate Anything for AWS ECS. I've moved to a self deploying setting. If you take a look at bin/scripts, I'm taking advantage of supervisord and gunicorn (for Python web development). But in context of EC2, you can simply point your AppSpec.yml to those scripts! Hope that helps everyone!
Before I start:
This is not a full answer. Not a complete walkthrough, but a lot of hints and some code that will help you with setting up certain AWS stuff like ALB and your files in your repo for this to work. This answer is more like several clues jumbled together from my sprint run trying to make ECS work last night.
I also don't have enough points to neither comment nor chat soo... here's the best thing I can offer.
Quick links (you should probably just skip these two points, though):
Check this out: https://docs.aws.amazon.com/codedeploy/latest/userguide/instances-ec2-configure.html
I don't have enough points to comment or chat... This won't be a full answer, as well, though, as I'm trying to first finish an ECS deploy from GH before moving on to EC2 from GH. Anyhow...
One last edit: this will sound like a marketing ploy but a correct implementation with GitHub actions and workflow_dispatch is located at Donate Anything's GitHub repository. You'll find the same ECS work located below in there. Do note that I changed my GitHub action to use Docker Hub since it was free (and to me cheaper if you're going to use ECS since AWS ECR is expensive).
Edit: The ECS deployment works now. Will start working on the EC2 deployment soon.
Edit 2: I added Donate Anything repo. Additionally, I'm not sure if direct EC2 deployment, at least for me, is viable since install scripts would kinda be weird. However, I still haven't found the time to get to EC2. Again, if anyone is willing to share their time, please do so and contribute!
I do want to warn everyone that SECURITY GROUPS are very important. That clogged me for a long time, so make sure you get them right. In the ECS tutorial, I teach you how I do it.
Full non-full answer:
I'm working on this issue right now in this repo and another for ECS here using GitHub actions. I haven't started too far on the EC2 one, but the basic rundown for testing is this:
CRUCIAL
You need to try and deploy from the AWS CLI first. This is because AWS Actions does not have a dedicated action for deploying to EC2 yet.
Write down each of these statements. We're going to need them later for the GitHub action.
Some hints when testing this AWS setup:
Before using CodeDeploy, you need an EC2 instance, an Application Load Balancer (you'll find it under Elastic Load Balancer), and a target group (which you create DURING the ALB setup). Go to target groups, right click on the group, and register your instance.
To deploy from CodeDeploy, create a new application. Create a new deployment group. I think, for your setup, you should do the in-place deployment type rather than the Blue/Green deployment type.
Finally, testing on the CLI, you should run the code you see here: https://docs.aws.amazon.com/codedeploy/latest/userguide/tutorials-wordpress-deploy-application.html#tutorials-wordpress-deploy-application-create-deployment-cli
Do note, you may want to start from here (using S3 as a location to store your latest code. You can delete it afterwards anyways, as I believe DELETE requests don't incur charges): https://docs.aws.amazon.com/codedeploy/latest/userguide/tutorials-wordpress-upload-application.html I personally don't know if that GitHub OAuth integration works. I tried once before (very amateur though, i.e. no clue what I was doing before) and nothing happened, soo... I'd just stick with that tutorial.
How your test rundown will look like:
For me, for my ECS repo, I just went a full 10 hours straight trying to configure everything properly step by step like the GitHub action. For you, you should do the same. Imagine you're the code: figure out where you need to start from.
Aha! I should probably figure out CodeDeploy first. Let's right an appspec.yaml file first! The appspec file is how CodeDeploy will work on the hooks for everything. Unfortunately, I'm current going through that problem here but that's because the EC2 and ECS syntax for AppSpec files are different. Luckily, EC2 doesn't have any special areas. Just get your files and hooks right. An example from my test:
version: 0.0
os: linux
files:
- source: /
destination: /code
hooks:
BeforeInstall:
- location: aws_scripts/install_dependencies
timeout: 300
runas: root
ApplicationStop:
- location: aws_scripts/start_server
runas: root
The GitHub action:
What you'll need at minimum:
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials#v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# TODO Change your AWS region here!
aws-region: us-east-2
The checking out of code is necessary to... well... get the code.
For the configuration of AWS credentials, you'll want to add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to your GitHub secrets with a proper IAM credential. For this, I believe the only IAM role needed is for full CodeDeploy stuff.
Deploying the code:
This is when that test code that you should've tried before reaching this step is for. Now that your workflow is setup, let's paste the code from the CLI into your action.
- name: Deploying with CodeDeploy
id: a-task
env:
an-environment-variable: anything you want
run: |
echo "Your CLI code should be placed here"
Sorry if this was confusing, not what you're looking for, or wanted a complete tutorial. I, too, haven't actually gotten this to work, but it's also been awhile since I last tried, and the last time I tried, I didn't even know what an EC2 instance was... I just did a standalone EC2 instance and used rsync to transfer my files. Hopefully what I've written was several clues that can guide you very easily to a solution.
If you got it to work, please share it on here: https://github.com/Andrew-Chen-Wang/cookiecutter-django-ec2-gh-action so that no one else has to suffer the pain of AWS deployment...
First, you need to go through this tutorial on AWS to set up your EC2 server, as well as configure the Application and Deployment Group in CodeDeploy: Tutorial: Use CodeDeploy to deploy an application from GitHub
Then, you can use the following workflow in GitHub Actions to deploy your code on push. You essentially use the AWS CLI to create a new deployment. Store the AWS credentials for the CLI in GitHub Secrets.
Here is an example for deploying a Node app:
name: Deploy to AWS
on:
push:
branches: [ main ]
jobs:
deploy:
name: Deploy AWS
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
app-name: ['your-codedeploy-application']
deployment-group: ['your-codedeploy-deploy-group']
repo: ['username/repository-name']
steps:
- uses: actions/checkout#v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node#v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install
- name: Build app
run: npm run build
- name: Install AWS CLI
run: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials#v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
aws-region: us-east-1
- name: Deploy to AWS
run: |
aws deploy create-deployment \
--application-name ${{ matrix.app-name }} \
--deployment-config-name CodeDeployDefault.OneAtATime \
--deployment-group-name ${{ matrix.deployment-group }} \
--description "GitHub Deployment for the ${{ matrix.app-name }}-${{ github.sha }}" \
--github-location repository=${{ matrix.repo }},commitId=${{ github.sha }}
when i try pushing image using drone plugin for amazon ECR i'm getting the following message:
"no basic auth credentials"
my .drone.yml file pipline:
publish-to-ecr:
image: plugins/ecr
repo: foo
registry: xxx.dkr.ecr.us-west-1.amazonaws.com
dockerfile: ./Dockerfile
tags:
- latest
access_key: xxx
secret_key: xxx
region: xxx
i am using the creds for pushing my local env and it is working
The problem was that the role I configured to the machine was not configured in the repository side as well
go to the repository, and under permissions add the role the following permissions: PutImage, CompleteLayerUpload, InitiateLayerUplaod
and it worked