Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 25 additions & 0 deletions aws-sso/.github/workflows/aws.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: AWS OIDC

on:
push:
- main

permissions:
id-token: write # required for AWS OIDC
contents: read # required to clone repository

jobs:
aws:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: earthly/[email protected]
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure AWS credentials
uses: aws-actions/[email protected]
with:
role-to-assume: <your OIDC role ARN>
aws-region: <your AWS region>
- name: Run +target
run: earthly --secret AWS_ACCESS_KEY_ID --secret AWS_SECRET_ACCESS_KEY --secret AWS_SESSION_TOKEN --ci +target
1 change: 1 addition & 0 deletions aws-sso/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cache
88 changes: 88 additions & 0 deletions aws-sso/Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
VERSION 0.8
FROM amazon/aws-cli

target:
BUILD +run --sso_region="us-east-2" --region="us-east-2" --args="sts get-caller-identity"

python:
FROM python:3
WORKDIR /workspace

ubuntu:
FROM ubuntu:jammy
WORKDIR /workspace
RUN apt update -y
RUN apt install -y curl unzip

login:
ARG EARTHLY_CI
IF [ "$EARTHLY_CI" = "false" ]
ARG --required sso_region
FROM +python
# https://github.com/benkehoe/aws-export-credentials
RUN pip install aws-export-credentials
BUILD +dev.login.open --sso_region=$sso_region
COPY +dev.login/aws /root/.aws
RUN aws-export-credentials --profile default --credentials-file-profile default
SAVE ARTIFACT /root/.aws/credentials /credentials
ELSE IF [ "$EARTHLY_CI" = "true" ]
RUN mkdir -p /root/.aws/
RUN --secret AWS_ACCESS_KEY_ID --secret AWS_SECRET_ACCESS_KEY --secret AWS_SESSION_TOKEN printf "[default]\naws_access_key_id=$AWS_ACCESS_KEY_ID\naws_secret_access_key=$AWS_SECRET_ACCESS_KEY\naws_session_token=$AWS_SESSION_TOKEN\n" >> /root/.aws/credentials
ELSE
RUN echo "bad value for EARTHLY_CI" && exit 1
END
SAVE ARTIFACT /root/.aws/credentials /credentials

dev.login.open:
ARG --required sso_region
LOCALLY
RUN command -v python3 >/dev/null || (echo "python3 is needed locally" && exit 1)
# unbuffer will preserve colored output if installed
IF command -v unbuffer
RUN unbuffer earthly +dev.login 2>&1 | tee /dev/tty | grep --line-buffered -Eo "[A-Z]{4}-[A-Z]{4}" | xargs -I % sh -c "python3 -m webbrowser https://device.sso.$sso_region.amazonaws.com/?user_code=%"
ELSE
RUN earthly +dev.login 2>&1 | tee /dev/tty | grep --line-buffered -Eo "[A-Z]{4}-[A-Z]{4}" | xargs -I % sh -c "python3 -m webbrowser https://device.sso.$sso_region.amazonaws.com/?user_code=%"
END

# Uses `aws sso login` to login to the AWS account
dev.login:
COPY --if-exists ./cache/ /root/.aws/
COPY sso_config /root/.aws/config
IF --no-cache ! aws sts get-caller-identity
RUN --no-cache aws sso login
SAVE ARTIFACT /root/.aws AS LOCAL ./cache
END
SAVE ARTIFACT /root/.aws /aws

# Run a command with the AWS CLI
run:
ARG --required sso_region
ARG --required region
ARG --required args
FROM +ubuntu
DO +INSTALL_CLI
DO +LOGIN --sso_region=$sso_region
ENV AWS_REGION=$region
RUN --no-cache aws $args

# Installs the AWS CLI
INSTALL_CLI:
FUNCTION
ARG TARGETARCH
IF [ "$TARGETARCH" = "amd64" ]
ARG aws_architecture="x86_64"
ELSE IF [ "$TARGETARCH" = "arm64" ]
ARG aws_architecture="aarch64"
ELSE
RUN echo "unknown architecture $TARGETARCH" && exit 1
END
RUN curl --location --fail --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-$aws_architecture.zip" --output "awscliv2.zip" && \
unzip -q awscliv2.zip && \
./aws/install && \
rm -rf awscliv2.zip aws

LOGIN:
FUNCTION
ARG --required sso_region
BUILD +login --sso_region=$sso_region
COPY (+login/credentials --sso_region=$sso_region) /root/.aws/credentials
15 changes: 15 additions & 0 deletions aws-sso/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Earthly with AWS SSO

This directory contains an example of using AWS SSO and OIDC with Earthly and GitHub Actions

## Usage

First, edit `sso_config` with your AWS SSO details. Edit `config` so that it points to the AWS region you'd like to use.

When used on a developer's machine, Earthly will run `aws sso login`, open a web browser, and login with AWS SSO. Credentials will be cached both in an image layer, and at `cache`.

When used with the `--ci` flag, e.g. in GitHub Actions, Earthly will accept the credentials passed in with Earthly Secrets.

`earthly +target` will run `aws sts get-caller-identity` showing how to run arbitrary AWS commands using this Earthfile.

The included GitHub Actions workflow authenticates with OIDC and passes the credentials to Earthly.
7 changes: 7 additions & 0 deletions aws-sso/sso_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[profile default]
sso_start_url =
sso_region =
sso_account_id =
sso_role_name =
region =
output = json
2 changes: 2 additions & 0 deletions bazel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
earthly-bazel-bin
earthly-bazel-tar
13 changes: 13 additions & 0 deletions bazel/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@io_bazel_rules_docker//java:image.bzl", "java_image")
load("@rules_java//java:defs.bzl", "java_binary")

java_binary(
name = "ProjectRunner",
srcs = glob(["src/main/java/com/example/*.java"]),
)

java_image(
name = "ProjectRunnerImage",
srcs = glob(["src/main/java/com/example/*.java"]),
main_class = "com.example.ProjectRunner",
)
51 changes: 51 additions & 0 deletions bazel/Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
VERSION 0.8

FROM ubuntu:22.04
WORKDIR /workspace

# Install OS-dependencies.
RUN apt-get update && \
apt-get install -y apt-transport-https wget gnupg gcc g++ gzip openjdk-11-jdk xz-utils

# Install Bazel.
ARG TARGETARCH
IF [ "$TARGETARCH" = amd64 ]
ARG BAZELARCH=x86_64
ELSE
ARG BAZELARCH=$TARGETARCH
END
RUN wget -q https://github.com/bazelbuild/bazel/releases/download/5.3.2/bazel-5.3.2-linux-$BAZELARCH -O /usr/local/bin/bazel && \
chmod +x /usr/local/bin/bazel && \
bazel && \ # Causes bazel to self-extract.
bazel --version

code:
COPY --dir BUILD WORKSPACE ./
COPY --dir src ./

build:
FROM +code
# Save Bazel's cache as a cache directory. This directory will be reused
# between runs.
ARG bazel_cache = "/root/.cache/bazel"
CACHE --persist "$bazel_cache"
RUN bazel build --@io_bazel_rules_docker//transitions:enable=false //:ProjectRunner
ARG bazel_out = "$(readlink -f ./bazel-out)"
ARG bazel_bin = "$(readlink -f ./bazel-bin)"
RUN chmod -R u+w "$bazel_out" # Some directories come out unwriteable.
SAVE ARTIFACT "$bazel_bin" AS LOCAL earthly-bazel-bin

run:
FROM +build
RUN ./bazel-bin/ProjectRunner

image:
FROM +code
ARG bazel_cache = "/root/.cache/bazel"
CACHE --persist "$bazel_cache"
RUN bazel build --@io_bazel_rules_docker//transitions:enable=false //:ProjectRunnerImage
ARG bazel_out_tar = $(bazel cquery --@io_bazel_rules_docker//transitions:enable=false ProjectRunnerImage-layer.tar --output starlark --starlark:expr=target.files.to_list\\(\\)[0].path)
# TODO: Earthly has no way of loading an image from a tar currently.
# The tar's contents could be unpacked into a directory, however,
# and that directory could become an image.
SAVE ARTIFACT "$bazel_out_tar" /image.tar AS LOCAL ./earthly-bazel-tar/image.tar
25 changes: 25 additions & 0 deletions bazel/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "io_bazel_rules_docker",
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
)

load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)

container_repositories()

load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")

container_deps()

load(
"@io_bazel_rules_docker//java:image.bzl",
_java_image_repos = "repositories",
)

_java_image_repos()
7 changes: 7 additions & 0 deletions bazel/src/main/java/com/example/Greeting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example;

public class Greeting {
public static void sayHi() {
System.out.println("Hi!");
}
}
7 changes: 7 additions & 0 deletions bazel/src/main/java/com/example/ProjectRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example;

public class ProjectRunner {
public static void main(String args[]) {
Greeting.sayHi();
}
}
8 changes: 8 additions & 0 deletions bazel/src/main/java/com/example/cmdline/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("@rules_java//java:defs.bzl", "java_binary")

java_binary(
name = "runner",
srcs = ["Runner.java"],
main_class = "com.example.cmdline.Runner",
deps = ["//:greeter"],
)
9 changes: 9 additions & 0 deletions bazel/src/main/java/com/example/cmdline/Runner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.cmdline;

import com.example.Greeting;

public class Runner {
public static void main(String args[]) {
Greeting.sayHi();
}
}
32 changes: 32 additions & 0 deletions c/Earthfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
VERSION 0.8
FROM alpine
WORKDIR /c-example

deps:
RUN apk --update add build-base cmake

build:
FROM +deps
COPY src src
RUN cmake src
RUN make
SAVE ARTIFACT c-example AS LOCAL c-example

docker:
COPY +build/c-example .
ENTRYPOINT ["/c-example/c-example"]
SAVE IMAGE --push earthly/examples:c

unit-test:
FROM +deps
RUN apk add cunit-dev
COPY src src
COPY test test
RUN cmake test
RUN make
RUN ./unit-test

all:
BUILD +build
BUILD +unit-test
BUILD +docker
4 changes: 4 additions & 0 deletions c/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.8.12)
project (c-example)
add_compile_options(-Wall -Wextra -pedantic -Werror)
add_executable(c-example main.c fibonacci.c)
4 changes: 4 additions & 0 deletions c/src/fibonacci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
int fibonacci(int n) {
if (n == 0 || n == 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
1 change: 1 addition & 0 deletions c/src/fibonacci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int fibonacci(int n);
25 changes: 25 additions & 0 deletions c/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <string.h>
#include "fibonacci.h"

void usage() {
fprintf(stderr, "Usage: ./fibonacci <num>\n");
}

int main(int argc, char** argv) {
int n;

if (argc != 2) {
usage();
return 1;
}

if (sscanf(argv[1], "%d", &n) < 0 || n < 0) {
fprintf(stderr, "Could not read a positive integer from the input\n");
usage();
return 1;
}

printf("fib(%d) = %d\n", n, fibonacci(n));
return 0;
}
6 changes: 6 additions & 0 deletions c/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 2.8.12)
project (c-example-unit-test)
add_compile_options(-Wall -Wextra -pedantic -Werror)
add_executable(unit-test test.c ../src/fibonacci.c)
target_link_libraries(unit-test cunit)

42 changes: 42 additions & 0 deletions c/test/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This example test suite is based on the code on the CUnit project's website.
* See there for more information: http://cunit.sourceforge.net/example.html
*/

#include <stdio.h>
#include "CUnit/Basic.h"
#include "../src/fibonacci.h"

void testFIBONACCI(void)
{
CU_ASSERT(fibonacci(0) == 0);
CU_ASSERT(fibonacci(1) == 1);
CU_ASSERT(fibonacci(3) == 2);
CU_ASSERT(fibonacci(15) == 610);
CU_ASSERT(fibonacci(23) == 28657);
}

int main()
{
CU_pSuite pSuite = NULL;

if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();

pSuite = CU_add_suite("TestSuite", NULL, NULL);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}

if ((NULL == CU_add_test(pSuite, "test of fibonacci()", testFIBONACCI)))
{
CU_cleanup_registry();
return CU_get_error();
}

CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}
Loading