diff --git a/actions/install-local/action.yml b/actions/install-local/action.yml index 47c8f74b..cdc29c69 100644 --- a/actions/install-local/action.yml +++ b/actions/install-local/action.yml @@ -72,6 +72,37 @@ runs: EOF echo "::add-mask::$(echo "$SECRET" | jq -r .SecretString | jq -r .host)" + - name: Get Tailscale configuration + if: steps.cache-binary.outputs.cache-hit == false + id: tailscale + shell: bash + run: | + TAILSCALE=$(cue export -e global.ci.providers.tailscale ./blueprint.cue) + CREDS=$(cue export -e global.ci.providers.tailscale.credentials ./blueprint.cue) + SECRET_ID=$(echo "$CREDS" | jq -r .path) + SECRET=$(aws secretsmanager get-secret-value --secret-id "$SECRET_ID") + + TAGS="$(echo $TAILSCALE | jq -r .tags)" + VERSION="$(echo $TAILSCALE | jq -r .version)" + CLIENT_ID="$(echo $SECRET | jq -r .SecretString | jq -r .client_id)" + CLIENT_SECRET="$(echo $SECRET | jq -r .SecretString | jq -r .client_secret)" + + echo "::add-mask::$CLIENT_ID" + echo "::add-mask::$CLIENT_SECRET" + + echo "client-id=$CLIENT_ID" >> $GITHUB_OUTPUT + echo "client-secret=$CLIENT_SECRET" >> $GITHUB_OUTPUT + echo "tags=$TAGS" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + - name: Install and configure Tailscale + if: steps.cache-binary.outputs.cache-hit == false + uses: tailscale/github-action@v3 + with: + oauth-client-id: "${{ steps.tailscale.outputs.client-id }}" + oauth-secret: "${{ steps.tailscale.outputs.client-secret }}" + tags: "${{ steps.tailscale.outputs.tags }}" + use-cache: "true" + version: "${{ steps.tailscale.outputs.version }}" - name: Build Forge CLI if: steps.cache-binary.outputs.cache-hit == false shell: bash diff --git a/actions/setup/README.md b/actions/setup/README.md index 7efacd6a..c17c0fc4 100644 --- a/actions/setup/README.md +++ b/actions/setup/README.md @@ -19,12 +19,11 @@ ci: { role: "arn:aws:iam::123456:role/ci" } earthly: { - credentials: { + satellite: credentials: { provider: "aws" path: "path/to/secret" } - org: "myorg" - satellite: "sat" + version: "latest" } } } @@ -52,10 +51,32 @@ jobs: The action will then perform the following: -1. Install the latest version of the Forge CLI -2. Authenticate to AWS via OIDC -3. Authenticate to Earthly Cloud using the credentials in the AWS Secrets Manager secret stored at `path/to/secret` -4. Set the default Earthly Cloud organization to `myorg` +1. **AWS Provider Setup** (if configured): + - Authenticate to AWS using OIDC with the configured role + - Login to Amazon ECR if a registry is specified + +2. **Docker Provider Setup** (if configured): + - Login to Docker Hub using credentials from the configured secret + +3. **GitHub Provider Setup** (if configured): + - Login to GitHub Container Registry (ghcr.io) using the GitHub token + +4. **Earthly Provider Setup** (if configured): + - Install Earthly CLI (latest or specified version) + - Configure remote Earthly satellite authentication if credentials are provided + +5. **Timoni Provider Setup** (if configured): + - Install Timoni CLI with the specified version + +6. **CUE Provider Setup** (if configured): + - Install CUE CLI with the specified version + +7. **KCL Provider Setup** (if configured): + - Install KCL CLI with the specified version + +8. **Tailscale Provider Setup** (if configured): + - Install and configure Tailscale using OAuth2 credentials + - Apply specified tags to the Tailscale node ### Configuring Providers @@ -70,7 +91,15 @@ The below list documents the expected format for each provider: - `username`: The username to login with - `password`: The password to login with 1. Earthly - - `token`: The Earthly Cloud token to login with + - `ca_certificate`: Base64-encoded string containing the common CA certificate for mTLS + - `certificate`: Base64 encoded string containing the (signed) client certificate used to authenticate with the satellite + - `private_key`: Base64 encoded string containing the private key used to authenticate with the satellite + - `host`: The address of the remote satellite in the form of `tcp://hostname:8372` +1. Tailscale + - `client_id`: The OAuth2 client ID used to authenticate with the Tailscale API + - `client_secret`: The OAuth2 secret key used to authenticate with the Tailscale API +1. GitHub + - `token`: The access token used to authenticate with GitHub If the secret uses a different format, the `maps` field of the secret can be used to map them correctly: @@ -103,7 +132,15 @@ Note that this _only_ works when run within the Catalyst Forge repository. ## Inputs -| Name | Description | Required | Default | -| ------------- | ---------------------------------------- | -------- | ----------------------- | -| forge_version | The version of the forge CLI to install | No | `"latest"` | -| github_token | The GitHub token used for authentication | No | `"${{ github.token }}"` | \ No newline at end of file +| Name | Description | Required | Default | +| ---------------------- | -------------------------------------------------------------------- | -------- | ----------------------- | +| github_token | The GitHub token used for authentication | No | `"${{ github.token }}"` | +| skip_aws | If true, skip authenticating with AWS and configuring ECR | No | `"false"` | +| skip_cue | If true, skips installing CUE CLI if the provider is configured | No | `"false"` | +| skip_docker | If true, skip authenticating to DockerHub | No | `"false"` | +| skip_earthly_install | If true, skip installing Earthly | No | `"false"` | +| skip_earthly_satellite | If true, skip adding authentication for the remote Earthly satellite | No | `"false"` | +| skip_github | If true, skip authenticating to GitHub Container Registry | No | `"false"` | +| skip_kcl | If true, skips installing KCL CLI if the provider is configured | No | `"false"` | +| skip_tailscale | If true, skips installing and authenticating with skip_tailscale | No | `"false"` | +| skip_timoni | If true, skips installing Timoni CLI if the provider is configured | No | `"false"` | \ No newline at end of file diff --git a/actions/setup/action.yml b/actions/setup/action.yml index 5e9a280c..0965bfdb 100644 --- a/actions/setup/action.yml +++ b/actions/setup/action.yml @@ -33,6 +33,10 @@ inputs: description: If true, skips installing KCL CLI if the provider is configured required: false default: "false" + skip_tailscale: + description: If true, skips installing and authenticating with skip_tailscale + required: false + default: "false" skip_timoni: description: If true, skips installing Timoni CLI if the provider is configured required: false @@ -275,3 +279,52 @@ runs: shell: bash run: | kcl version + + # Tailscale Provider + - name: Get Tailscale provider configuration + id: tailscale + if: inputs.skip_tailscale == 'false' + shell: bash + run: | + echo "==== Tailscale Setup =====" + BP=$(forge dump .) + + TAILSCALE=$(echo "$BP" | jq -r .global.ci.providers.tailscale) + if [[ "$TAILSCALE" != "null" ]]; then + CONFIGURED="true" + VERSION=$(echo "$BP" | jq -r .global.ci.providers.tailscale.version) + if [[ "$VERSION" == "null" ]]; then + VERSION="latest" + fi + + TAGS=$(echo "$BP" | jq -r .global.ci.providers.tailscale.tags) + if [[ "$TAGS" == "null" ]]; then + TAGS="" + fi + + SECRET=$(forge secret get --project . global.ci.providers.tailscale.credentials) + CLIENT_ID=$(echo "$SECRET" | jq -r .client_id) + CLIENT_SECRET=$(echo "$SECRET" | jq -r .client_secret) + + echo "::add-mask::$CLIENT_ID" + echo "::add-mask::$CLIENT_SECRET" + + echo "client-id=$CLIENT_ID" >> $GITHUB_OUTPUT + echo "client-secret=$CLIENT_SECRET" >> $GITHUB_OUTPUT + echo "tags=$TAGS" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + else + echo "Not configuring Tailscale" + CONFIGURED="false" + fi + + echo "configured=$CONFIGURED" >> $GITHUB_OUTPUT + - name: Install and configure Tailscale + if: inputs.skip_tailscale == 'false' && steps.tailscale.outputs.configured == 'true' + uses: tailscale/github-action@v3 + with: + oauth-client-id: "${{ steps.tailscale.outputs.client-id }}" + oauth-secret: "${{ steps.tailscale.outputs.client-secret }}" + tags: "${{ steps.tailscale.outputs.tags }}" + use-cache: "true" + version: "${{ steps.tailscale.outputs.version }}" diff --git a/blueprint.cue b/blueprint.cue index 8062009b..7455ad63 100644 --- a/blueprint.cue +++ b/blueprint.cue @@ -60,6 +60,15 @@ global: { ] version: "v0.11.0" } + + tailscale: { + credentials: { + provider: "aws" + path: "global/ci/tailscale" + } + tags: "tag:cat-github" + version: "latest" + } } secrets: [ { diff --git a/lib/schema/blueprint/global/providers/cue_types_gen.go b/lib/schema/blueprint/global/providers/cue_types_gen.go index 51806fb9..e86b0c5a 100644 --- a/lib/schema/blueprint/global/providers/cue_types_gen.go +++ b/lib/schema/blueprint/global/providers/cue_types_gen.go @@ -105,10 +105,25 @@ type Providers struct { // KCL contains the configuration for the KCL provider. Kcl *KCL `json:"kcl,omitempty"` + // Tailscale contains the configuration for the Tailscale provider. + Tailscale *Tailscale `json:"tailscale,omitempty"` + // Timoni contains the configuration for the Timoni provider. Timoni *Timoni `json:"timoni,omitempty"` } +type Tailscale struct { + // Credentials contains the OAuth2 credentials for authenticating to the + // Tailscale network. + Credentials *common.Secret `json:"credentials,omitempty"` + + // Tags is a comma-separated list of tags to impersonate. + Tags string `json:"tags,omitempty"` + + // Version contains the version of Tailscale to install. + Version string `json:"version,omitempty"` +} + type Timoni struct { // Install contains whether to install Timoni in the CI environment. Install bool `json:"install,omitempty"` diff --git a/lib/schema/blueprint/global/providers/main.cue b/lib/schema/blueprint/global/providers/main.cue index cb435b8d..6fe143e0 100644 --- a/lib/schema/blueprint/global/providers/main.cue +++ b/lib/schema/blueprint/global/providers/main.cue @@ -22,6 +22,9 @@ package providers // KCL contains the configuration for the KCL provider. kcl?: #KCL + // Tailscale contains the configuration for the Tailscale provider. + tailscale?: #Tailscale + // Timoni contains the configuration for the Timoni provider. timoni?: #Timoni } diff --git a/lib/schema/blueprint/global/providers/tailscale.cue b/lib/schema/blueprint/global/providers/tailscale.cue new file mode 100644 index 00000000..82328149 --- /dev/null +++ b/lib/schema/blueprint/global/providers/tailscale.cue @@ -0,0 +1,15 @@ +package providers + +import "github.com/input-output-hk/catalyst-forge/lib/schema/blueprint/common" + +#Tailscale: { + // Credentials contains the OAuth2 credentials for authenticating to the + // Tailscale network. + credentials?: common.#Secret + + // Tags is a comma-separated list of tags to impersonate. + tags?: string + + // Version contains the version of Tailscale to install. + version?: string +}